如何使用sed删除文件中匹配特定模式且长度大于或小于特定长度的行



我可以分别删除具有特定模式且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

最新更新