将vim替换转换为对sed,awk或类似unix命令的反向引用

时间:2014-09-26 07:16:52

标签: regex unix vim awk sed

您好我有一个命令,我一直用它来处理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中运行吗?

非常感谢

4 个答案:

答案 0 :(得分:1)

您可以使用Vim中的:global解决此问题,而不是使用多行正则表达式(确实可能很慢):

:global/^R1/.+3,.+5delete _

这将搜索以R1开头的所有行,然后删除三到五行(进入黑洞寄存器_)。

答案 1 :(得分:0)

使用sed:

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解决方案总是如此。