2 行間の 1 行を削除する方法

2 行間の 1 行を削除する方法

ファイル内にはこのようなレコードが何百万件もあります

echo "NEW Cell"
grep "2553,24" out.2A25.20090308.64436.7.HDF.txt.text = 22.58   5.39  82.09 237
echo "NEW Cell"
grep "2555,20" out.2A25.20090308.64436.7.HDF.txt.text = 24.72   5.58  82.05 237
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120
echo "NEW Cell"
grep "2560,24" out.2A25.20090308.64436.7.HDF.txt.text = 19.38   5.54  82.30 170
echo "NEW Cell"

ここで、「新しいセル」を含む行の間にある唯一の行であるという条件で、「grep」を含む行を削除したいと思います。つまり、新しいセルの間に grep の行が 1 つある場合は、この行を削除する必要があります。

これを行う方法?

出力は次のようになります。

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

答え1

AWK解決:

awk 'NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }
     /NEW Cell/{ f=1; n=NR+2; r=$0; next }
     f && n-NR==1 && /^grep /{ gr=$0; next }1' file
  • /NEW Cell/{ f=1; n=NR+2; r=$0; next }- ラインに遭遇するとNEW Cell

    • f=1= アクティブフラグを設定するf=1
    • n=NR+2-n処理する次の行の最大数を設定します(次の 2 行)
    • r=$0- ラインをキャプチャする
    • next- 次のレコードへジャンプ
  • f && n-NR==1 && /^grep /-キーワードn-NR==1で始まる2行目( によって保証される)に遭遇するとgrep

    • gr=$0; next-grep行をキャプチャし、次の(3番目の)レコードにジャンプする
  • NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }- 3番目の重要なラインに遭遇したとき(によって保証されるNR==n

    • if (/NEW Cell/) { f=0 }- 処理済みセクションの3行目に以下が含まれている場合NEW Cell- 現在の処理をリセットしますf=0(以前にキャプチャされた行はすべてスキップされます)
    • else print r ORS gr- それ以外の場合は、以前にキャプチャしたすべての行を印刷します

出力:

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

答え2

コンパクトなソリューションsed:

sed '/NEW Cell/!{H;d;};x;/\n.*\n/!d'

行にNEW Cell実行が含まれていない場合はH、ホールド スペースに行を追加し、dその行の処理を停止します。

したがって、以降のコマンドは行にのみ適用されますNEW Cell。 はxパターン スペースとホールド スペースを交換するため、行はホールド スペースに配置され、さらに行を追加できます。一方、パターン スペースには最後のNEW Cell行に追加されたすべてのものが含まれます。 要件は、行間に複数の行があることであるNEW Cellため、パターン スペースには少なくとも 2 つの改行が必要です。 そうでない場合は、出力せずに削除します/\n.*\n/!d

答え3

初歩的なawk...

バージョン 1 では、grepOP の説明に従う行のみが削除されます。

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
     else { f=1; s=$0 } } ! /^echo/ { print; f=0 } \
     ! /^echo/ && ! /^grep/ { print }' inputfile

バージョン 2 では、単独のgrep行と、OP のサンプル出力に続く先行する非 grep 行が削除されます。

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
    else { f=1; s=s "\n" $0 } } /^echo/ { s=$0; f=0 } \
    ! /^echo/ && ! /^grep/ { print }' inputfile

バージョン 2 の読み取り可能な形式...

/^grep/ { 
   if (found) {  # found==true : already encountered first grep line
       if (length(save) > 0) {
          print save
          save=""
       }
       print
   } else {
       found=1
       save=save "\n" $0  # append the first grep line to saved preceding line
   }
}

/^echo/ { 
    save=$0  # save this line for possible later printing
    found=0
}

# print anything else
! /^echo/ && ! /^grep/ { print }

この長い形式は、内容をファイル (例awkfile) およびに配置することで実行できますawk -f awkfile inputfile

答え4

gawk '
/\n.+\n/{
    printf("%s%s", RS, $0);
}' RS='echo "NEW Cell"\n' input.txt

説明:

  1. RS='echo "NEW Cell"\n'- はRS入力レコードの区切り文字で、デフォルトでは改行です。現在は に変更されているecho "NEW Cell"\nため、この文字列のすべての出現が削除され、その間にあるすべての文字がレコード項目になります。
  2. /\n.+\n/{- このパターンに一致するレコードのみ - 改行、1 つ以上の文字、改行。したがって、複数行のレコードにのみ一致し、単一行のレコードは 1 つしかないため一致しません\n
  3. printf("%s%s", RS, $0);RS- 先頭に( )を付けてレコードを出力しますecho "NEW Cell"\n

出力

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

関連情報