2016-09-15 16 views
1

我可以删除特定格式的文本并缩短​​或更长的文本sed '/^.\{25\}..*/d' -i FILE,但如何合并在sed模式和长度?如何删除某个文件中符合特定格式并长于或短于特定长度的文件中的行

含有A系应该是包含B应该是包含C应该是所有其他线3和字符

之间8

线10和15个字符

之间

线20和字符之间25

应从文件中删除

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 

回答

2

这是你如何与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 
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

+0

考虑使用一个变量,而不是每行调用'length()'最多6次,所有的'*'都不做任何事情。 –

+1

@EdMorton:好主意。但是,除非我知道O.P.是否可以使用'awk'解决方案,否则不想花费更多时间。此外,这将需要使用“{if(...)....}”的查看形式。是不是模式/动作形式的首选; - >?我明天会为你的想法添加一个编辑。祝你们好运。 – shellter

+1

这只是对{n = length()}/A /&&n> 19 && n <26 ||的调整。 ....'。 –

1

用AWK,你可以简单地写条件的布尔表达式,你不是卡住试图让出了正则表达式的条件:

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