問題は、コマンド全体をSEDと同じ行に入れることができないことです。そうしましたが、次のファイルでは機能しません。私の例:
<file>Documents/time/text1</file> //2X slash + 2 words to remove !!
<file>Commun/text2</file> //1X slash to remove + 1 words to remove
<file>Current/text3</file> //1X slash to remove + 1 words to remove
このコードがオンラインで機能しないのはなぜですか?
sed 's/Documents//g' | sed 's/time//g' | sed 's/Commun//g' | sed 's/Current//g' | sed 's/Current//g' | sed '/<file>/s|<file>/|<file>|' | sed '/<file>/s|<file>/|<file>|' tracklist.txt > newtracklist.txt
答え1
OPの現在のスクリプトパイプラインを実行すると、入力ファイル()の内容がstdoutとして印刷され、パイプラインが中断されsed
ますtracklist.txt
(つまり、他の出力がないか、コマンドプロンプトに戻りません)。はい推測するOPが言及したときに言及した内容です。it does not work
...??
主な問題:入力ファイル()は、最後のスクリプトではなく最初のスクリプトtracklist.txt
の引数として提供する必要があります。sed
sed
おすすめ:
# instead of this:
sed 's/Documents//g' | ... | sed '/<file>/s|<file>/|<file>|' tracklist.txt
^^^^^^^^^^^^^
# do this:
sed 's/Documents//g' tracklist.txt | ... | sed '/<file>/s|<file>/|<file>|'
^^^^^^^^^^^^^
sed
OPパイプラインの更新版を実行すると、次のようになります。
<file>text1</file>
<file>text2</file>
<file>text3</file>
HTML / XMLを解析するためのより良いツールがありますが、OPがそれを使用する必要がある場合は、よりsed
効率的な方法で同じ結果を生成することができます。
アイデアにはsed
スクリプトが必要です。
sed -E 's|(<file>).*/([^/]+</file>)|\1\2|' tracklist.txt
どこ:
-E
- 拡張正規表現サポートの有効化(<file>)
- (最初のキャプチャグループ)文字列と一致します。<file>
([^/]+</file>)
- (2番目のキャプチャグループ)/
の後に文字列がないすべての文字と一致します。</file>
.*/
- 2つのキャプチャグループ間のすべてが/
\1\2
- 代替文字列は、一緒に追加された2つのキャプチャグループで構成されています。- メモ:これは、OPが提供する特定の入力に対して機能します。入力がOPの入力例に示されている形式と異なる形式の場合は、調整が必要になる場合があります。
OPのサンプル入力の場合、以下が生成される。
<file>text1</file>
<file>text2</file>
<file>text3</file>
答え2
入力XMLファイルが与えられると
r
ルートノードの追加:
<r>
<file>Documents/time/text1</file>
<file>Commun/text2</file>
<file>Current/text3</file>
</r>
パスワード:
xidel --xquery '
<r>{
for $x in //file
return <file>{tokenize($x, "/")[last()]}</file>
}</r>
' --output-format=xml --output-node-indent file.xml
生産する:
<?xml version="1.0" encoding="UTF-8"?>
<r>
<file>text1</file>
<file>text2</file>
<file>text3</file>
</r>
説明する:
ここではsed
間違ったツールを使用するのではなく、正しいパーサーを使用していますXPath
(XQuery
前者は後者のサブセットです)XML
。
xidel
HTML/XML ジョブのスイス軍用ナイフです。
使用法:
xidel ... file.xml > new_file.xml
編集したい場合飛行中:
xidel ... file.xml | sponge file.xml
sponge
~から牛に似た一種の栄養 more-utils
。
答え3
使用幸せ(以前のPerl_6)
~$ raku -MXML -e 'my $xml = open-xml( $*ARGFILES.Str );
for $xml.elements( :RECURSE(0), :TAG{"file"} ) -> $E {
my $old = $E.contents[0];
my $new = XML::Text.new( text => $old.text.match(/ <?after "/"> <-[/]>+ $/) );
$E.replace( $old, $new );
}; .say for $xml;' file.xml
または:
% raku -MXML -e 'my $xml = open-xml( $*ARGFILES.Str );
for $xml.elements( :RECURSE(0), :TAG{"file"} ) -> $E {
my $old = $E.contents[0];
my $new = XML::Text.new( text => $old.text.path.basename );
$E.replace( $old, $new );
}; .say for $xml;' file.xml
Rakuは、高度な機能を備えたPerlファミリのプログラミング言語です。文法テキストを解析するために使用されます。 Raku / Rakudo自体に加えて、コミュニティメンバーはRaku / Rakudoエコシステムのモジュールをサポートしています。これらのモジュールの1つは(楽出身)XML
モジュール。
OPの他の質問と同様に、XML
-moduleを使用するRakuでは、(たとえば)置換を1に制限できます。最上階と2)。 TAG内でのみ可能です<file>
。これはelements
、制約内で繰り返すようにコードを設定することによって行われます:RECURSE(0), :TAG{"file"}
。参考までに、TAG
必要に応じてすべての深さですべてのsを繰り返すことができます。名前付き引数を設定して:RECURSE(Inf)
削除すると、制限はFalseに設定されます。:TAG
:TAG
上記の最初の答えは、交換に適したタグ/レベルを識別します。これは、各要素の内部部分(つまりTAGではない部分)が実際にオブジェクトであるcontents[0]
変数に割り当てられていることを確認します。オブジェクトを文字列として抽出し、目的のオブジェクトを見つけます。次に、変更されたキーと値のペアを使用して新しい()オブジェクトを作成()します。これから -module のルーチンがこれを行います。$old
XML::Text
$old
.text
match
XML::Text.new
$new
text => 'value'
XML
replace
replace( $old, $new )
上記の2番目の答えは、最初の答えを賢く変形させたものです。 OPはパス名を編集しようとしているため、IO::Path
Rakuオブジェクトクラスに関連するルーチンを使用できます。 Rakuの.IO
ルーチンはテキストを有効なパス名として理解し、Rakuの.basename
ルーチンは最終ファイル名を返します。 Rakuには、さまざまなプラットフォームで正しい(/
または\
)パス区切り文字を使用するメカニズムがあるため、このアプローチはコードの移植性を向上させる可能性があります。
入力例(@GillesQuénotに感謝!):
<r>
<file>Documents/time/text1</file>
<file>Commun/text2</file>
<file>Current/text3</file>
</r>
出力例:
<?xml version="1.0"?><r>
<file>text1</file>
<file>text2</file>
<file>text3</file>
</r>
https://github.com/raku-community-modules/XML
https://docs.raku.org/type/IO/Path
https://rakudo.org/
https://raku.org