次のファイルからdef
AND(行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
!
d
jkl
def
jkl
必要な数の正規表現を一般化するには、次のようにします。
sed '
/regexp1/!b
/regexp2/!b
/regexp3/!b
d'
\|
標準語ではありません。基本正規表現(BRE) 演算子。これをサポートする実装はほとんどありませんsed
。標準BREにはORまたはAND演算子はありません。標準ERE(拡張正規表現、sed -E
多くのsed
実装がそうであるように)はOR(|
)をサポートしますが、ANDはサポートしません。
これ全開実装にはsed
AND演算子(&
)があります。改善-A
正規表現を有効または有効にします-X
が、次のことを行う必要があります。
sed -A '/.*def.*&.*jkl.*/d'
A&B
と両方一致する文字列の一致として。A
B
sed
Perlに似た正規表現実装(sed -P
ast-openやsed -R
withなど)をサポートすることで、ssed
予測演算子を使用できます。
sed -P '/^(?=.*def)(?=.*jkl)/d'
(?=...)
後に()、任意の数の文字(.*
)、その後にdef
任意の数の文字の後に()が続く場合、行の先頭に一致しますjkl
。
grep
これ以上サポートされていない実装がないため、-P
次sed
のようになります。
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つの答えは、-ne
Rakuのルーチンと一緒に(自動印刷ではなく)1行ずつフラグを使用しますgrep
。次の3つの答えは、@terdonのPerl(5)答えに対応するRakuです。
()コードの最初の2行はgrep
2つの異なるメカニズムを使用しているので興味深いです。最初のものは結合all
(通常はRakuのコレクションから呼び出されます)を使用しますが、2番目の例はTrue / Falseをブールしたコードブロックgrep
で実行されます{}
。
最初の2つの()結果grep
の良い変形は、ルーチン(:k
、、、、)で使用できる追加の引数を利用することです。たとえば、単にペア(「副詞」引数)を追加すると、結果を番号付きペアとして出力するようにコードに指示します。:v
:kv
:p
grep
:p
raku -ne '.put if .grep( { !/def/ || !/jkl/ }, :p );'
出力例(インデックス付き):
0 => 1. abc def ghi
2 => 3. jkl mno pqr
4 => 5. vwx yza bcd