您好我有一个命令,我一直用它来处理vim中的文本文件;寻找一个字符串R1然后删除3行,2行下面的字符串。 这在vim中运行良好,但是对于大文件来说它非常慢:
:1,$s/\(r1.*\n\)\(\(.*\n\){2}\)\(\(.*\n\)\{3}\)/\1\2/g
示例:
R1 30049 109769 109769
101598 281921
6.56608e+006 2.82861e+006
1.19658e+006 1.19658e+006
-515145 -515145
-223257 627520
-101598 -281921
-6.56608e+006 -2.82861e+006
23.125 23.125
271.7 272.46
500 500
会变成:
R1 30049 109769 109769
101598 281921
6.56608e+006 2.82861e+006
-101598 -281921
-6.56608e+006 -2.82861e+006
23.125 23.125
271.7 272.46
500 500
这个命令(或类似命令)可以更快地在unix终端中的sed或awk中运行吗?
非常感谢
答案 0 :(得分:1)
您可以使用Vim中的:global
解决此问题,而不是使用多行正则表达式(确实可能很慢):
:global/^R1/.+3,.+5delete _
这将搜索以R1
开头的所有行,然后删除三到五行(进入黑洞寄存器_
)。
答案 1 :(得分:0)
sed -n '/^R1/{p;n;p;n;p;n;n;n;n};p;' file.txt
使用备份编辑文件:
sed -n -i.bak '/^R1/{p;n;p;n;p;n;n;n;n};p;' file.txt
答案 2 :(得分:0)
你可以通过perl来做到这一点,
$ perl -00pe 's/(\bR1.*\n(?:.*\n){2})(.*\n){3}/\1/g' file
R1 30049 109769 109769
101598 281921
6.56608e+006 2.82861e+006
-101598 -281921
-6.56608e+006 -2.82861e+006
23.125 23.125
271.7 272.46
500 500
答案 3 :(得分:0)
sed是单行上简单替换的优秀工具,但对于其他任何东西只需使用awk:
$ awk '/R1/{start=NR+3;end=start+2} NR<start || NR>end' file
R1 30049 109769 109769
101598 281921
6.56608e+006 2.82861e+006
-101598 -281921
-6.56608e+006 -2.82861e+006
23.125 23.125
271.7 272.46
500 500
上面说过在包含R1(NR + 3)的行之后开始删除3行并且在此之后停止2行(开始+ 2)。如果你有其他范围或其他一些模式或其他条件要处理,那么使其工作的调整是清晰和简单的。尝试调整sed解决方案以删除20行而不是3行。
如果由于某种原因您更喜欢sed解决方案的简洁性,只需使用单字符变量名称并丢失空格:
awk '/R1/{s=NR+3;e=s+2}NR<s||NR>e' file
它比sed更简洁,但仍然更加可维护,可扩展等,因为多线问题的awk解决方案总是如此。