web-dev-qa-db-ja.com

2番目の文字列の一致が見つかるまで、文字列に一致する行の途中からすべての行を削除します

ファイルに出力されたエラーメッセージを削除しようとしています。私はこれを持っています:

 addr:1122c:1234:
 addr:11230:5678:
 addr:11223:01Error:abcdef(x, y) = z, value = a
Error:hijklm(v, q) = w, value = b
Error:nopqrst(x, y) = z, value = d
Error:uvwxyz(l, m) = z, value = e
Error:1234(u, t) = z, value = f
Error:567(r, s) = z, value = g
err_total = 9846, err_sub = 0, err_mask = 239
1 Duration: xyz, abc
0 Duration: pqr, def
23:
 addr:11238:4567:
 addr:1123c:8901:

次のアドレスが表示されるまで、すべてのエラーメッセージを削除する必要があります。必要な出力は次のとおりです。

 addr:1122c:1234:
 addr:11230:5678:
 addr:11223:0123:
 addr:11238:4567:
 addr:1123c:8901:

私が試してみました:

sed -i "/\bError\b/d" file_name

ただし、これはErrorから始まる行を削除し、Error stringが中央から始まった行を削除しませんでした。

私は正規表現が初めてなので、説明が本当に役立ちます。

編集:私はsed -i '/Error/,/addr/d' filenameを使用していますが、これは行全体を削除し、探しているものを提供しません。

3
lost_wanderer

sedは、Multiline Matchingではあまり良くありません。
あなたはそれをだまして好きなことをすることができますが、imo Perlの方が扱いやすいです。

これを試して:

Perl -pe 'BEGIN{undef $/;}; s/Error.*?(^[0-9]* Duration: [^\n]*\n)+//smg;'

説明:

  • BEGIN { do_something; }:始めに何かをする
  • undef $/:行末を無視
  • s///代替
  • Error.*「エラー」で始まる文字列に一致します。
  • ?次の一致またはこの場合は一致グループで停止するため、前の一致を貪欲にしないでください...
  • ()+一致グループを作成します。少なくとも1回は一致する必要があります(+)。
  • ^[0-9]* Duration: [^\n]*\n:Durationを含む行全体に一致します。

via

4
pLumo

Error:」行を削除するのではなく、必要な行だけを抽出してみてください。

grep -E '^ addr:' file_name | sed -e 's/Error:.*//'
2
waltinator

これにより、探している出力が生成されます。

$ cat file_name | grep -v \
    -e '^Error:' \
    -e '^err_total' \
    -e '^.*[0-9] Duration:' | \
    sed ':a;$!N;s/Error:.*\n\(.*[0-9]\):/\1:/;ta;P;D'

すべてのErrorerr_total、および12345 Duration:をすべて削除します。次に、出力を中断するError: ...を検索し、改行(\n)を削除し、次に出現する番号(.*[0-9]:)を検索して、現在の行に追加します。

1
Simon Sudler