我能够删除某些模式的行,并且分别比某个长度更短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
答案 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