如何使用与某个模式匹配且长度或短于特定长度的sed删除文件中的行

时间:2016-09-15 15:58:19

标签: 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

3 个答案:

答案 0 :(得分:3)

您可以使用 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

答案 1 :(得分:1)

使用awk并且您可以简单地将条件写为布尔表达式,并且不会因为尝试从正则表达式中创建条件而陷入困境:

$ awk '(/A/ && /^.{20,25}$/) || (/B/ && /^.{10,15}$/) || (/C/ && /^.{3,8}$/)' file
1234567890 A 1234567890
12345 B 12345
1 C 1

答案 2 :(得分:0)

这是一个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

我已将您的边界数字增加/减少一,以消除使用<=>=进行测试的需要(这些稍微更昂贵的测试。非常大文件它可能花费你30秒(只是一个猜测!))。

(不要让任何空格字符在这些续行结束后的\之后进入)。

(另外,如果需要,可以删除\个字符并将其折叠到一行。)

这可以增强以接受变量值,我在这里包含一个简短的例子,根据您的需求完成它可以被视为学习的机会; - )

awk -v lim1=10 -v lim2=26 '/.*A.*/ && length($0) > lim1  && length($0) < lim2 ...

IHTH