删除以模式 A 或 B 开头的行,除非它们包含模式 C 或 D

删除以模式 A 或 B 开头的行,除非它们包含模式 C 或 D

我有一个这样的文件:

1 foo
1 bar
1 someOtherString
2 contains bar and more
2 test
3 contains a random string
4 some other string
2 don't remove this line bar
2 but remove this line
14 keep this line
21 and also this line
7 bar

从这个文件中,我想获取这个文件:

1 foo
1 bar
2 contains bar and more
3 contains a random string
4 some other string
2 don't remove this line bar
14 keep this line
21 and also this line
7 bar

基本上:

  • 保留所有不以“1”或“2”开头的行
  • 保留包含“foo”或“bar”的所有行
  • 删除所有其他行
  • 保持订单完整

答案1

考虑名为 的文件中的数据file。实现示例结果的要求与您发布的语句略有不同:

  • file保留符合以下任一条件的 所有行:
    • 不要以1nor开头2(这是一个数字后跟一个空格)
    • 包含foobar
  • 删除所有其他行
  • 保持订单完整

perl这可以通过匹配两个表达式并在匹配时打印该行(按顺序)来表达:

perl -ne '( !/^(1 |2 )/ or /foo|bar/ ) and print' file

事后想想,整个需求的表达方式可能略有不同:

  • 依次对于每一行
    • 如果该行不是以1or开头,则打印该行2
    • foo如果该行包含或,则打印该行bar

这映射到awk非常方便:

awk '!/^(1 |2 )/ || /foo/ || /bar/' file

在这两种情况(perlawk)中,RE^(1 |2 )都可以通过导出公因子并将其重写为来简化^[12]

perl -ne '( !/^[12] / or /foo|bar/ ) and print' file
awk '!/^[12] / || /foo/ || /bar/' file

答案2

使用sed

$ sed '/^[12]\>/ { /foo/ !{ /bar/ !d; }; }' file
1 foo
1 bar
2 contains bar and more
3 contains a random string
4 some other string
2 don't remove this line bar
14 keep this line
21 and also this line
7 bar

上面的代码用于sed测试每行是否以非单词字符开头12后跟非单词字符(\>如果您愿意,可以用单个空格替换)。如果没有,则打印该行。如果是,则测试该行的子字符串foo。如果该子字符串存在,则打印该行。如果不存在,则对 进行类似的测试bar,如果匹配则打印该行,如果不匹配则删除该行。

从倒着读逻辑d:不匹配bar且不匹配foo但以1or开头的行被删除2

答案3

使用 Raku(以前称为 Perl_6)

raku -ne '.put if .grep( !/^ [ 1 | 2 ] \s / | / foo | bar / );'  

或者

raku -ne '.put if .grep( { !/^ [ 1 | 2 ] \s /} | / foo | bar / );'  

或者

raku -ne '.put if .grep( (none /^ [ 1 | 2 ] \s /) | / foo | bar / );'  

输入示例:

1 foo
1 bar
1 someOtherString
2 contains bar and more
2 test
3 contains a random string
4 some other string
2 don't remove this line bar
2 but remove this line
14 keep this line
21 and also this line
7 bar

示例输出:

1 foo
1 bar
2 contains bar and more
3 contains a random string
4 some other string
2 don't remove this line bar
14 keep this line
21 and also this line
7 bar

上面是 @roaima 的 Perl5 代码的粗略翻译,尽管在 Raku 中这确实是一个grep操作。在 Raku 中,您可以使用!否定运算符(如上所示,带/不带周围{...}代码块)或使用连接(与Raku 中none相关)来测试是否存在模式。Sets

\s您可能会注意到正则表达式中包含一个字符。那是因为未声明的 ( \s) 空白和/或“...正则表达式中未加引号的空格通常会被忽略...”默认情况下在 Raku 中,使代码更具可读性。请参阅下面的链接。

https://docs.raku.org/language/regexes#Sigspace
https://raku.org

答案4

我们可以使用环视来进行此类多条件搜索,从而获利:

$ grep -vP '^(?=[12]\h)(?!.*(?:foo|bar))' file

Python可以配合它的re模块根据搜索结果状态进行匹配和过滤。

python3 -c 'import re, sys
with open(sys.argv[1]) as f:
  print(*filter(lambda x: re.match(r"(?![12]\s)",x) or re.search(r"foo|bar",x),f),sep="",end="")
' file

相关内容