我有一个这样的文件:
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
保留符合以下任一条件的 所有行:- 不要以
1
nor开头2
(这是一个数字后跟一个空格) - 包含
foo
或bar
- 不要以
- 删除所有其他行
- 保持订单完整
perl
这可以通过匹配两个表达式并在匹配时打印该行(按顺序)来表达:
perl -ne '( !/^(1 |2 )/ or /foo|bar/ ) and print' file
事后想想,整个需求的表达方式可能略有不同:
- 依次对于每一行
- 如果该行不是以
1
or开头,则打印该行2
foo
如果该行包含或,则打印该行bar
- 如果该行不是以
这映射到awk
非常方便:
awk '!/^(1 |2 )/ || /foo/ || /bar/' file
在这两种情况(perl
和awk
)中,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
测试每行是否以非单词字符开头1
或2
后跟非单词字符(\>
如果您愿意,可以用单个空格替换)。如果没有,则打印该行。如果是,则测试该行的子字符串foo
。如果该子字符串存在,则打印该行。如果不存在,则对 进行类似的测试bar
,如果匹配则打印该行,如果不匹配则删除该行。
从倒着读逻辑d
:不匹配bar
且不匹配foo
但以1
or开头的行被删除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