sedを使用して結果をバッファに保存し、それを他のsedコマンドのパターンとして使用する

sedを使用して結果をバッファに保存し、それを他のsedコマンドのパターンとして使用する

だから私はsed内のバッファー(モードバッファー、ホールドバッファーなど)の存在を理解し始め、sedコマンド(例えば置換)の結果を他のコマンドに保存/保存したり、再利用する簡単な方法があるかと思いました。 /sed電話か。

パイプ出力を置き換えるとしましょう。

somecommand | sed 's/somepattern/somethingelse/g'

上記の交換の出力を何とか再利用したいです。どうすればいいですか?以下が利用可能であることを知っています。

  1. 一時ファイル(例:raw mv + echoなどを使用)
  2. 別のパイプセット、sed呼び出し、およびxargs(例:sed ... | xargs -I {} sed ...)

しかし、上記の両方が私を止めるでしょうただsedへの単一の呼び出しを使用してください(ここではこれが私が望むものです)。

そのような方法があることがわかったら、次のようにしたでしょう。

somecommand | sed -i 's/somepattern/somethingelse/g;s/[reusing result from last substitution]/someotherthings/g' file

[ ]の間の部分は、置換結果をパターンなどとして再利用します。

考えられる解決策を見つけるためにsed文書を参照しようとしましたが、例はあまりありません。

すべてのフィードバック/回答を歓迎します。

PS:上記の例の出力は実際にはポイントではありませんが、より明確にするために次のようsomecommandに置き換えることができます。

echo "hello"

文字通り。

私が試した別の方法は理解しやすい例です。

#!/bin/sh
echo -e "hello\nworld" | sed -n '
l #enable debugging
'/hello/' { # match the string from the echo pipe/command output
    s/hello/test/ #do a substitution
    p #print
    x # keep in
}'

x前半を正常に完了しました。他の交換(または他のsed呼び出し/タスク/コマンド)と一緒に使用できるように、その中にあるものを使用する方法を知る必要があります。

私が試したことは次のとおりです(しかし今回は失敗しました)。

#!/bin/sh
echo -e "hello\nworld" | sed -n '
l #enable debugging
'/hello/' { # match the string from the echo pipe/command output
    s/hello/test/ #do a substitution
    p #print
    x # keep in
    s/x/somethingelse/ # <---- what is failing
}'

これはうまくいきません。ここにあるものを何でも得る方法があるようですがx、わかりません。

答え1

私が理解しているように、過去の代替の出力を別の代替のパターンとして使用して、ある種の動的検索パターンが必要です。

例を使用すると役に立つと思います。このようなファイルが与えられると

green2
gold1
blue3
gold2
red4
more gold2 to find

1これで、各行をに置き換えて2結果の行を保存して、その行が再び表示されるときにいくつかの操作を実行できます。このサンプルファイルでは置き換えたい場合がありますが、gold2他のファイルでは異なる可能性があるため、わかりません。出力は次のようになります。

green2
gold2
blue3
replace
red4
more replace to replace

現実の世界にも同様の作業があるかもしれませんsed

sed -e 's/1/2/;tfound' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P;d' -e ':found' -e h inputfile

概念は、結果の行を保持バッファに格納し、逆参照を使用して各行を保持バッファに一致させることです。詳細:

  • s/1/2/明らかな部分は1次のとおりです。2
  • tfound:found置換時に分岐マークを示します。この場合、その行は予約済みスペースに保存され、h置き換えられた行が印刷されます(d印刷したくない場合は要素を追加できます)。
  • これで、ホールド空間パターンが発生しているかどうかを確認するライン部分が表示されます。Gホールド空間は現在のパターン空間に追加されるため、パターン空間には以下が含まれます。
  • s/\(..*\)\(.*\)\n\1$/replace\2/現在の行には2つのグループが形成されます。最初のグループは\1改行文字の後に繰り返されるので、これは予約済みスペースの動的パターンです(注:..*パターンは少なくとも1文字でなければならないため、空の予約語を使用しないでください)。一致するスペース)2は行の残りの部分であるため、削除しないでください。交換のよう\2にリサイクルします。
  • 代替項目がある場合はその行を印刷できますが、代替項目がない場合は追加した内容を削除する必要があります。これでこれを行うことができますが、コマンドs/\n.*//を使用してP最初の行のみを印刷し、デフォルトのd出力を避けるように選択することもできます。

これは、連続的に発生する動的検索パターンを1つだけ置き換えることに限定されますが、ループを簡単に追加して複数の置換に対して機能するようにすることができます。

修正する: OPは、2番目のステップが元の一致行とすべての後続行(新しい一致まで)に適用される必要があることを明確にしました。

hello
world
and test it

しなければならない

世界を変えて変えろ

この場合、他のグルーロジックと同じメカニズムを使用します。

sed -ne '/hello/{s//test/;h;}' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P'

オプションは、すべての必須出力がコマンドを介して実行されるため、-nすべてのデフォルト出力を抑制します。P一致する文字列(hello)に置き換え(空のパターンは最後のパターンを再利用することを意味します)を実行し、それを保持バッファに入れてから次のコマンドを実行すると、次の置換も同じ行で行われます。

アップデート2: リンクされた例では、helloこれらの行はまったく変更しないでください。いくつかの修正でこれを行うことができます。

sed -ne '/hello/{h;s//test/;x;}' -e 'G;s/\(..*\)\(.*\)\n\1$/replace\2/;P'

関連情報