8

トランザクションでいっぱいのファイルから、パターン一致の両側の2行を削除しようとしています。つまり。一致するものを見つけて、その前の2行を削除し、その後の2行を削除してから、一致するものを削除します。これを元のファイルに書き戻します。

したがって、入力データは

D28/10/2011
T-3.48
PINITIAL BALANCE
M
^

私のパターンは

sed -i '/PINITIAL BALANCE/,+2d' test.txt

ただし、これはパターン一致後に2行を削除してから、パターン一致を削除するだけです。sedを使用して元のファイルから5行すべてのデータを削除する論理的な方法を見つけることができません。

4

6 に答える 6

8

awkワンライナーがその仕事をするかもしれません:

awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file

テスト:

kent$  cat file
######
foo
D28/10/2011
T-3.48
PINITIAL BALANCE
M
x
bar
######
this line will be kept
here
comes
PINITIAL BALANCE
again
blah
this line will be kept too
########

kent$  awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file
######
foo
bar
######
this line will be kept
this line will be kept too
########

説明を追加

  awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}   #if match found, add the line and +- 2 lines' line number in an array "d"
      {a[NR]=$0} # save all lines in an array with line number as index
      END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' #finally print only those index not in array "d"
     file  # your input file
于 2012-08-03T10:52:47.767 に答える
5

sedそれを行います:

sed '/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'

これは次のように機能します。

  • sedのパターンスペースに文字列が1つしかない場合は、別の文字列に結合します
  • 2つしかない場合は、3つ目に結合します
  • LINE + LINE + LINE with BALANCEのパターンにナッチする場合は、次の2つの文字列を結合し、それらを削除して最初に進みます。
  • そうでない場合は、パターンから最初の文字列を出力して削除し、パターンスペースをスワイプせずに最初に移動します

最初の文字列にパターンが表示されないようにするには、スクリプトを変更する必要があります。

sed '1{/PINITIAL BALANCE/{N;N;d}};/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'

ただし、削除される文字列に別の文字列がある場合は失敗しますPINITIAL BALANCE。ただし、他のソリューションも失敗します=)

于 2012-08-03T12:34:03.127 に答える
2

そのようなタスクのために、私はおそらくPerlのようなより高度なツールに手を伸ばすでしょう:

perl -ne 'push @x, $_;
          if (@x > 4) {
              if ($x[2] =~ /PINITIAL BALANCE/) { undef @x }
                  else { print shift @x }
          }
          END { print @x }' input-file > output-file

これにより、入力ファイルから5行が削除されます。これらの行は、一致前の2行、一致した行、および一致後の2行になります。削除する行の総数を変更して@x > 4(これにより5行が削除されます)、一致する行が変更され$x[2]ます(これにより、削除される3行目の一致が行われるため、一致する前に2行が削除されます)。

于 2012-08-03T10:49:53.527 に答える
2

よりシンプルで理解しやすいソリューションは次のとおりです。

awk '/PINITIAL BALANCE/ {print NR-2 "," NR+2 "d"}' input_filename \
    | sed -f - input_filename > output_filename

awkは、問題の行を削除するsed-scriptを作成するために使用され、結果はoutput_filenameに書き込まれます。

これは、他の回答よりも効率が悪い可能性がある2つのプロセスを使用します。

于 2021-04-11T19:15:13.217 に答える
1

これはあなたのために働くかもしれません(GNU sed):

sed ':a;$q;N;s/\n/&/2;Ta;/\nPINITIAL BALANCE$/!{P;D};$q;N;$q;N;d' file
于 2012-08-03T18:31:19.737 に答える
0

このコードをファイルに保存しますgrep.sed

H
s:.*::
x
s:^\n::
:r
/PINITIAL BALANCE/ {
    N
    N
    d    
}

/.*\n.*\n/ {
    P
    D
}
x
d

次のようなコマンドを実行します。

`sed -i -f grep.sed FILE`

次のいずれかで使用できます。

sed -i 'H;s:.*::;x;s:^\n::;:r;/PINITIAL BALANCE/{N;N;d;};/.*\n.*\n/{P;D;};x;d' FILE
于 2012-08-03T13:05:59.503 に答える