用给定的字符串替换vim中的第n个模式

时间:2017-06-30 10:34:55

标签: regex vim

我有一个这种格式的文件:

field1     | field2         | field3    | field4    | field5    | field6     | field7
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever

我想在vim中用0; 0; 0; 0; 0替换第二个CSV列(field4)。我试过了

/|\s\+\(\d\+;\)\+

看看我是否可以匹配但是只要我添加最后一个\+它就匹配整行,所以我将无法替换它。我也试过\{1\}希望它会重复一次模式,然后再次\(\)同样的模式,但我的vim似乎不喜欢{}(RHEL 5.5 vim 7.0) 0.237)。

我会选择sed,awk或perl,但我真的想更好地掌握wim的正则表达式。

3 个答案:

答案 0 :(得分:1)

这会将第4列(由|分隔)替换为 0;0;0;0;0

%s/^\([^|]\+|\)\{3\}\zs[^|]\+/ 0;0;0;0;0 /

<强>之前

field1     | field2         | field3    | field4    | field5    | field6     | field7
irrelevant | doesn't matter | 1;2;3;4;5 | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
alpha      | beta           | anything  | 1;2;3;4;5 | 1;2;3;4;5 | don't care | whatever
a | b | c | d | e | f | g

<强>后

field1     | field2         | field3    | 0;0;0;0;0 | field5    | field6     | field7
irrelevant | doesn't matter | 1;2;3;4;5 | 0;0;0;0;0 | 1;2;3;4;5 | don't care | whatever
alpha      | beta           | anything  | 0;0;0;0;0 | 1;2;3;4;5 | don't care | whatever
a | b | c | 0;0;0;0;0 | e | f | 

<强>释

替换模式会跳过由|分隔的前三个字段并替换第四个字段

  • %s对文件中的每一行执行替换
  • ^匹配行的开头
  • [^|]\+|匹配不是|加上尾随|
  • 的所有内容
  • \(...\)\{3\}匹配任何...
  • 的三次出现
  • \zs表示用于替换的匹配的开始
  • [^|]匹配下一个|
  • 之前的所有内容

答案 1 :(得分:0)

使用awk我这样做了:

#!/bin/awk -f

BEGIN { 
    FS="|";
    OFS="|";
}

{    
    for(i = 1; i < NF; i++) {
        if(i == 4) {
            printf "2;0;0;0;0;0;0;0;0;0;0;0;0;0;0";
        } else {
            printf "%s", $i;
        }
        printf OFS;
    }
    printf RS;
}

END { 
}

我想使用vim,但我会使用最适合这项工作的工具。

答案 2 :(得分:0)

如果您想在glob("testFolder/*")中执行此操作,请使用:

vim

但是,由于处理行和列,我强烈建议您使用:%s/\v(\|\s*\d+(;\d+)*\s*\|\s*)\d+(;\d+)*/\12;0;0;0;0;0;0;0;0;0;0;0;0;0;0/ 执行此作业。您也可以使用以下命令改进建议的awk命令:

awk