別のコマンドでパイピングするときは、生のパターンスペースを一致する文字列に制限します。

別のコマンドでパイピングするときは、生のパターンスペースを一致する文字列に制限します。

テキストファイルがあり、内部のすべてのスペースをハイフンに置き換えたい[[]]括弧は入れ子ではなく常に一致します)。以下は例です。

$ cat test.txt 
abc [[foo]] xyz
abc [[foo bar]] xyz
abc [[foo bar baz]] xyz [[something else]]

したがって、希望の出力は次のようになります。

abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]

sed私は角かっこ内の文字列を一致させ、置換するフラグでe結果を再実行するために使用できると思いました。sedしかし、問題は、一致する文字列がコマンドとして実行されるだけでなく、全体のパターンスペース(全体行のように見えます)も実行されることです。

$ sed -E 's@(\[\[)(.+)(\]\])@sed -e "s/ /-/g" <<< "\1\2\3"@gpe' test.txt 
abc sed -e "s/ /-/g" <<< "[[foo]]" xyz
sh: 1: Syntax error: redirection unexpected

abc sed -e "s/ /-/g" <<< "[[foo bar]]" xyz
sh: 1: Syntax error: redirection unexpected

abc sed -e "s/ /-/g" <<< "[[foo bar baz]]" xyz
sh: 1: Syntax error: redirection unexpected

eフラグを介して実行される項目を一致する文字列に制限する方法はありますか?そうでない場合は、この問題をどのように解決する必要がありますかsed

ベストアンサー1

シェルに渡される修飾子を制限する方法はありませんが、e次のようにできます。

$ sed -E ':a;s@(.*\[\[)([^][]* [^][]*)(\]\].*)@printf "%s%s%s" "\1" "$(printf "\2" | sed "s/ /-/g")" "\3"@e;ta' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]

複数の置換処理はループで行われ、一致の欲張りな性質のため、実際には置換が逆の順序で実行される。

また、whichをe使用すると入力リダイレクトを/bin/shサポートしない可能性があることに注意してください<<<(したがって同等のパイプを使用してくださいprintf "\2" | sed "s/ /-/g")。


Perlがオプションの場合は、次のように元の意図に近い操作を実行できます。

$ perl -pe 's/(?<=\[\[)(.*?)(?=\]\])/$1 =~ s: :-:rg/ge' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]

Perlは非グリッド修飾子を提供するので?g外部置換のフラグを使用して、1行に複数の置換をより一般的に処理できます。

おすすめ記事