grepが一致しないようにしたいテキストファイルとパターンがあります。問題は、前の行も一致しないようにしたいということです。
私のファイル:
line 1
line 2
pattern
line 4
私はそれを試しました、cat file | grep -v pattern
結果は次のようになります。
line 1
line 2
line 4
それから試してみましたが、cat file | grep -B 1 pattern
結果は次のとおりです。
line 2
pattern
ただし、一緒に使用すると、次のような結果がcat file | grep -v -B 1 pattern
得られます。
line 2
出力をどのように作成できますか?
line 1
line 4
答え1
私はgrep
ファイルから1行を抽出するときにのみこのツールを使用する傾向があるため、テキストでより複雑な編集を実行する必要がある場合は別のツールを使用します。
ここのすべての解決策は、パターンがテキスト内で複数回表示されることを前提としており、パターンが発生する行と直前の行を削除します。最初の2つの解決策は、パターンが連続した行で一致する場合に問題が発生します。
sed
パターンを一致させ、/pattern/
コマンドN
とをトリガーすることができますd
。このコマンドは、次の行をバッファに追加し、両方を削除します。
sed '/pattern/ { N; d; }' file
なぜなら、あなたはその行を捨てたいからです今後パターンを一致させるためにデータを逆に入力しますsed
。最後の行から始めてファイルの先頭に移動します。sed
完了したら、データを再び反転します。
tac file | sed '/pattern/ { N; d; }' | tac
このtac
ユーティリティはGNU coreutilsの一部です。ほとんどの非GNUシステムをtail -r
代わりに使用できますtac
(tail(1)
マニュアルを確認してください)。
パターンが 2 つの連続した行と一致する場合、最初の行が削除されるため、最初の行より前の行は削除されません。
ed
エディタを使用してください。
printf '%s\n' 'g/pattern/ -1,. d' ,p Q | ed -s file
g/pattern/ -1,. d
これにより、ファイルの内容にコマンドが適用されます。このコマンドは、一致する各行を検索し、その行pattern
とその前の行を削除します。
最終,p
編集Q
コマンドは、ファイル全体を印刷して保存せずにエディタを終了します。
パターンが2つの連続した行と一致する場合は、最初の行の前の行を削除してから、2番目の行の前の行を削除します。
(最後の文は正しい文を書いてみると、きっとそのまま書く文章なのが明らかだ。 )
grep
非標準ですが一般的に使用される-B
オプションを使用して、削除する必要がある行番号を指定することもできます。この数値は、sed
生データで実行されるスクリプトに変換できます。
grep -n -B1 'pattern' file | sed 's/[:-].*/d/' | sed -f /dev/stdin file
grep
質問のテキストに基づいてコマンドが出力されます。
2-line 2
3:pattern
...最初のsed
コマンドはそれをsed
編集コマンドに変換し、2d
その後に3d
(「2行と3行削除」)が続きます。sed
パイプラインの最後のコマンドはこの編集スクリプトを取得し、元のテキストに適用します。
このバリアントは最初に削除する必要があるすべての行を見つけてから削除する2段階のアプローチを使用するため、パターンに一致する連続行の問題はありません(テキストを最初に読み取るときに行を削除する代わりに)。
答え2
tacでawkを使用すると、一致するパターンの前の行を好きなだけ削除できます。
$ tac file | awk '/pattern/{c=2} !(c&&c--)' file | tac
line 2
line 1
削除する行数(最大一致行まで)を変更してください。たとえば、数字97とその前の94行を削除c=2
します。c=5
$ seq 100 | tac | awk '/97/{c=95} !(c&&c--)' | tac
1
2
98
99
100
それでは、awkの代わりにsedを試してみてください:-)。
バラより印刷には sed- または awk-a-line-follow-a-matching-pattern を使用します。これと他の関連イディオムの説明です。
答え3
メモ:file
このコードは、出力と一致する各行に重複した行または部分文字列がない場合にのみ機能しますgrep -B1 pattern file
。
たとえば、file
次の行を含む場合:
line 1
line 2
line 2
pattern
line 1 line 2
line 3
そして私が使用する出力はgrep -B1 pattern file | grep -v "$(cat)" file
あなたが期待するものとは異なります。
line 1
line 3
この問題を解決するための最良の方法は、次を使用することです。コサロナンダの答え
解決策(上記のように、重複した行または部分文字列がない場合にのみ機能します)
これはbash
私にとって効果的です(より良い方法があると思います)。
grep -B1 pattern file | grep -v "$(cat)" file
zsh
上記のコマンドには影響はありません。理由はわかりません。ただし、次のものを使用できます。
grep -B1 pattern file | { val="$(cat)" ; grep -v "$val" file; }
ポリスチレンcat your_file | grep pattern
重複するので使用する必要はありません。使用する必要がありますgrep pattern your_file
答え4
pcregrep
Ultilineモードを使用できますM
。
pcregrep -Mv '\n.*pattern'
最初の行がパターンと一致すると、削除されません。この問題は、以下を使用して解決できます。
pcregrep -Mv '(\n)?.*pattern'
((...)
この部分は\n
明らかに必要ですが、バージョン8.39ではなぜ機能しないのかわかりません\n?.*pattern
。)[\n]?.*pattern