2つの文字列一致を含む行を削除する

2つの文字列一致を含む行を削除する

次のファイルからdefAND(行2と4)を含むすべての行を削除するにはどうすればよいですか?jklその一致がフィールドの部分文字列一致にも機能するようにしたいと思います。ファイルのフィールドはスペースで区切られます。

$ cat test2.txt 
1. abc def ghi
2. def ghi jkl
3. jkl mno pqr
4. jkl def stu
5. vwx yza bcd

私はブールOR()を使って\|これをしました。

$ sed '/def.*jkl\|jkl.*def/d' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

ANDたとえば、より単純なブール構文がありますか$ sed '/defANDjkl/d'

sed '/def&jkl/d'、、、sed '/def&&jkl/d'としようとしましたが、何も動作しませんsed '/def\&jkl/d'sed '/def\&\&jkl/d'

答え1

具体的には、sed次のようにできます。

sed -e '/def/!b' -e /jkl/d

()が見つからない場合、最初のe表現はbオーバーフローします(行を印刷するオプションを渡していないため-n)。見つかると、2番目の要素がオーバーフローします。したがって、最終的には、とが見つかった場合にのみ行が削除されます。def!djkldefjkl

必要な数の正規表現を一般化するには、次のようにします。

sed '
  /regexp1/!b
  /regexp2/!b
  /regexp3/!b
  d'

\|標準語ではありません。基本正規表現(BRE) 演算子。これをサポートする実装はほとんどありませんsed。標準BREにはORまたはAND演算子はありません。標準ERE(拡張正規表現sed -E多くのsed実装がそうであるように)はOR(|)をサポートしますが、ANDはサポートしません。

これ全開実装にはsedAND演算子(&)があります。改善-A正規表現を有効または有効にします-Xが、次のことを行う必要があります。

sed -A '/.*def.*&.*jkl.*/d'

A&Bと両方一致する文字列の一致として。AB

sedPerlに似た正規表現実装(sed -Past-openやsed -Rwithなど)をサポートすることで、ssed予測演算子を使用できます。

sed -P '/^(?=.*def)(?=.*jkl)/d'

(?=...)後に()、任意の数の文字(.*)、その後にdef任意の数の文字の後に()が続く場合、行の先頭に一致しますjkl

grepこれ以上サポートされていない実装がないため、-Psedのようになります。

grep -vP '^(?=.*def)(?=.*jkl)'

携帯性がさらに良くなります。

答え2

部分文字列の一致も削除基準になると述べたので、次のawk手順が機能します。

~$ awk '!(/def/ && /jkl/)' test.txt
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

これにより、次の行だけが印刷されます。いいえdef「行が合計と一致する」条件がjkl満たされます。

必ず必要に応じてsed適応できます。回答:Stéphane Chazelas:

~$ sed -e '/def/!b' -e '/jkl/d' test.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

答え3

代わりにPerlを使用することもできます。この場合、構文は以下よりも理解しやすいですsed

$ perl -ne 'print unless /def/ && /jkl/' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

または

$ perl -ne '/def/ && /jkl/ || print' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

でも:

$ perl -ne '(/def/ && /jkl/) ? next : print' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

答え4

Raku(以前のPerl_6)の使用

raku -ne '.put  unless .grep: all(/def/ , /jkl/);'

または

raku -ne '.put if .grep: { !/def/ || !/jkl/ };'

または(@terdonのPerl5コードに対応するRaku):

raku -ne '.put unless /def/ && /jkl/;'

または

raku -ne '/def/ && /jkl/ || .put;'

または

raku -ne '(/def/ && /jkl/) ?? {next} !! .put'

入力例:

1. abc def ghi
2. def ghi jkl
3. jkl mno pqr
4. jkl def stu
5. vwx yza bcd

出力例:

1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

簡単に言えば、最初の2つの答えは、-neRakuのルーチンと一緒に(自動印刷ではなく)1行ずつフラグを使用しますgrep。次の3つの答えは、@terdonのPerl(5)答えに対応するRakuです。

()コードの最初の2行はgrep2つの異なるメカニズムを使用しているので興味深いです。最初のものは結合all(通常はRakuのコレクションから呼び出されます)を使用しますが、2番目の例はTrue / Falseをブールしたコードブロックgrepで実行されます{}

最初の2つの()結果grepの良い変形は、ルーチン(:k、、、、)で使用できる追加の引数を利用することです。たとえば、単にペア(「副詞」引数)を追加すると、結果を番号付きペアとして出力するようにコードに指示します。:v:kv:pgrep:p

raku -ne '.put if .grep( { !/def/ || !/jkl/ }, :p );' 

出力例(インデックス付き):

0 => 1. abc def ghi
2 => 3. jkl mno pqr
4 => 5. vwx yza bcd

https://raku.org

関連情報