web-dev-qa-db-ja.com

その行または次の行に特定の文字列が含まれていない場合に行を印刷する方法

Input.txt:

    8B0C
    remove
    8B0D
    remove
    8B0E
    remove
    8B0F
    8B10
    remove
    8B14
    remove
    8B15
    remove
    8B16
    remove
    8B17
    remove
    8AC0
    8AC1
    remove
    8AC2
    remove
    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

必要な出力:

    8B0F
    8AC0
    8AE4
    8AE5

その行または次の行に「削除」が含まれていない場合、その行を印刷したい。私はsolaris5.10、KSHを使用しています。

8
ayrton_senna

sedの場合:

sed '$!N;/remove/!P;D' infile

これにより、Next行がパターンスペースにプルされ(la!t行の$でない場合)、パターンスペースがremoveと一致するかどうかがチェックされます。そうでない場合(パターンスペースの2行のいずれにも文字列removeが含まれていないことを意味します)、最初の\newline文字までPrintsします(つまり、最初の行を出力します)。次に、最初の\newline文字までDeletesし、サイクルを再開します。このように、パターンスペースには2行を超える行がありません。


パターン空間を調べるためにNの前後にPを追加すると、DlNサイクルを理解するのがおそらく簡単になります。

sed 'l;$!N;l;/remove/!P;D' infile

したがって、例の最後の6行のみを使用します。

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

最後のコマンド出力:

    8AC3 $ 
 8AC3\n remove $ 
 remove $ 
 remove\n 8AE4 $ 
 8AE4 $ 
 8AE4\n 8AE5 $ 
 8AE4 
 8AE5 $ 
 8AE5\n 8AE6 $ 
 8AE5 
 8AE6 $ 
 8AE6\n remove $ 
 remove $ 
削除$

ここに簡単な説明があります:

cmd出力cmd
l     8AC3$                  N # read in the next line
l     8AC3\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                N # read in the next line
l     remove\n    8AE4$      D # delete up to \n (pattern space matches so no P)
l     8AE4$                  N # read in the next line
l     8AE4\n    8AE5$        # pattern space doesn't match so print up to \n
P     8AE4                   D # delete up to \n
l     8AE5$                  N # read in the next line
l     8AE5\n    8AE6$        # pattern space doesn't match so print up to \n
P     8AE5                   D # delete up to \n 
l     8AE6$                  N # read in the next line
l     8AE6\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                # last line so no N 
l     remove$                D # delete (pattern space matches so no P)
14
don_crissti
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 
5
glenn jackman
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

上記のメソッドは、レコードline-by-lineを読み取るのではなく、multi-lineあるレコードセパレーター(RS)から次の(またはファイルの終わり)へのレコード– RSは「削除」行自体です(末尾の `\ nを含む)。

!RT testは、最後の行がRS行でない場合に必要です。
RTgawk-ismは、現在のレコードのRSの実際のテキストです。
gensubgawk-ismです。

一致するマーカー行をチェックする必要がある場合行のどこかで「削除」するのに対して- equals「削除」し、レコード区切りを次のように変更します。

`RS="[^\n]*remove[^\n]*\n"`  

出力:

8B0F
8AC0
8AE4
8AE5
2
Peter.O