次の連続した行を含むファイルがあります。
macroa{abc def 123 ghi}
macrob{abc 123 xyz}
Macrobの最初の文字列がMacroaと同じであることを確認して削除したいと思います。結果は次のとおりです。
macroa{abc def 123 ghi}
macrob{123 xyz}
フルファイル方式を使用していますここ私のコマンドは
sed -e '1h;2,$H;$!d;g' -e 's/\(macroa{\([a-z]*\) [^\n]*\)\n\(macrob{\)\2 /\1\n\3/g' in > out
しかし、これはうまくいきません。私は何が間違っていましたか?ありがとうございます。
答え1
GNUでスクリプトをテストしましたが、sed
期待した結果が出ました。ただし、これは標準で定義されていない内部的に置き換えて使用するため、sed
他のバージョンに移植することはできません。\n
[]
これを置き換えて使用すると簡単に回避できます。
sed -e '1h;2,$H;$!d;g' -e 's/\(macroa{\([a-z]*\) [^\n]*\)\(\nmacrob{\)\2 /\1\3/g'
式でこれを使用するには、[]
トリックを使用できます。このy
コマンドを使用して、改行文字を通常の文字に置き換えてから再変更します。この場合は、以下を使用してください|
。
sed -e '1h;2,$H;$!d;g' -e 'y/\n|/|\n/;s/\(macroa{\([a-z]*\) [^|]*\)\(|macrob{\)\2 /\1\3/g;y/\n|/|\n/'
これは一般的な解決策ですが、見苦しいと思います。ほとんどの場合、改行文字を除くすべてのコードには印刷可能な文字が含まれているため、代わりに書き込むこと[^\n]
ができます。[[:print:]]
sed 'H;1h;$!d;g;s/\(macroa{\([a-z]*\) [[:print:]]*\)\n\(macrob{\)\2 /\1\n\3/g'
(イニシャルも1h;2,$H
減りましたH;1h
。)
don_crisstiのコメントを考慮して、この種の問題を解決する一般的な方法はループを実行することですN;P;D
。常にN
拡張行を追加し、2行を一緒に処理してから、1行目を印刷してP
パターンD
スペースから削除して2行目を続行します。
sed 'N;s/\(macroa{\)\([a-z]* \)\(.*\nmacrob{\)\2/\1\2\3/;P;D'
答え2
awk
代わりに使用できる場合sed
$ awk -F'[{ ]' 'c && c-- && $1=="macrob" && $2==s{sub(s" ", "")}
$1=="macroa"{c=1; s=$2} 1' ip.txt
macroa{abc def 123 ghi}
macrob{123 xyz}
-F'[{ ]'
{
フィールド区切り文字として、またはスペース文字を使用する$1=="macroa"{c=1; s=$2}
最初のフィールドはmacroa
初期化カウンタを使用し1
、2番目のフィールドは変数に格納されます。カウンタは、次のいずれかの行を確認する必要があるかどうかを決定します。c && c--
これはカウンタがゼロでない限り真です。c=1
この場合、カウンタはこれが真の場合にのみ追加条件に関係なくゼロに移動します。したがって、連続した行のみが一致します。$1=="macrob" && $2==s
前提条件sub(s" ", "")
文字列と空白文字の削除
- 追加資料:sedまたはawkを使用して、一致するパターンと一致する行を印刷します。