我可以分别删除具有特定模式且sed '/^.{,20}$/d' -i FILE
短于特定长度或sed '/^.{25}..*/d' -i FILE
长于特定长度的行,但如何在sed中统一模式和长度?
包含A
的行应该在20到25个字符之间
包含B
的行应该在10到15个字符之间
包含C
的行应该在3到8个字符之间
所有其他行应该从文件
中删除1234567890 A 1234567890
12345 A 12345
1 A 1
1234567890 B 1234567890
12345 B 12345
1 B 1
1234567890 C 1234567890
12345 C 12345
1 C 1
输出应该是这样的
1234567890 A 1234567890
12345 B 12345
1 C 1
sed:
$ sed -ne '/A/ s/^(.{20,25})$/1/p; /B/ s/^(.{10,15})$/1/p; /C/ s/^(.{3,8})$/1/p;' file
1234567890 A 1234567890
12345 B 12345
1 C 1
如何工作:
-ne - suppress printing pattern
/A/ - look for pattern A
^(.{20,25})$ - line with 20-25 characters
/1/p - print pattern space
使用awk,您可以简单地将条件写为布尔表达式,您不需要尝试从regexp中创建条件:
$ awk '(/A/ && /^.{20,25}$/) || (/B/ && /^.{10,15}$/) || (/C/ && /^.{3,8}$/)' file
1234567890 A 1234567890
12345 B 12345
1 C 1
awk
解决方案
awk '/.*A.*/ && length($0) > 19 && length($0) < 26
|| /.*B.*/ && length($0) > 9 && length($0) < 16
|| /.*C.*/ && length($0) > 2 && length($0) < 9' test1.dat
编辑
这是一个更有效的版本,我们只得到一次length($0)
awk '{len=length($0)}
/.*A.*/ && len > 19 && len < 26
|| /.*B.*/ && len > 9 && len < 16
|| /.*C.*/ && len > 2 && len < 9' test1.dat
1234567890 A 1234567890
12345 B 12345
1 C 1
我已经将您的边界数增加/减少了1,以消除使用<=
和>=
(稍微更昂贵的测试)进行测试的需要。对于一个非常大的文件,它可能会花费你30秒(只是一个猜测!))。
(不要在这些连续行末尾的之后插入任何空白字符)。
(如果需要的话,您也可以删除字符并将其折叠成一行)
这可以增强以接受可变值,我在这里包含一个简短的示例,根据您的需要完成它可以被视为学习的机会;-)
awk -v lim1=10 -v lim2=26 '/.*A.*/ && length($0) > lim1 && length($0) < lim2 ...
IHTH