如何从以下文件中删除所有包含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
xpressionb
会溢出(因为我们没有传递该-n
选项而打印该行),如果找到,则第二个eletes 会溢出。所以最后只有当 和 都被发现时,该行才会被删除。def
!
d
jkl
def
jkl
要推广到任意数量的正则表达式,您可以执行以下操作:
sed '
/regexp1/!b
/regexp2/!b
/regexp3/!b
d'
请注意,这\|
不是一个标准基本正则表达式(BRE)运营商。很少sed
有实现支持它。标准 BRE 既没有 OR 也没有 AND 运算符。标准 ERE(扩展正则表达式,正如sed -E
许多sed
实现所支持的那样)确实支持 OR ( |
) 但不支持 AND。
这ast-开放的实现中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
由于您声明 substring-match 也将构成删除标准,因此以下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/ };'
OR(Raku 相当于 @terdon 的 Perl5 代码):
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
简而言之,前两个答案使用-ne
(非自动打印)逐行标志以及 Raku 的grep
例程。接下来的三个答案是 @terdon 的 Perl(5) 答案的 Raku 等效项。
前两行 ( grep
) 代码很有趣,因为它们使用两种不同的机制:第一行使用连接all
(通常在 Raku 中的集合上调用),而第二个示例在代码块grep
上运行{}
,该代码块布尔化为 True/错误的。
前两个 ( 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