2016-07-14 60 views
1

我需要修改设置的字符串,看起来像这样的:使用多种模式VIM取代

debug("some random text: val " + arg1); 

debug("some random text: val " + arg1 + " val2 " + arg2); 

debug("some random text: val " + getValue(1) + " val2" + getValue(2) + "."); 

或其任何类似组合。例如,有可能是0个或多个“ARGS”,所有需要更换

debug("some random text: val ", arg1); 

debug("some random text: val {} val2 {}", arg1, arg2); 

debug("some random text: val {} val2 {}.", getValue(1), getValue(2)); 

基本上采取每一个+匹配的说法。* +与{替代},并把匹配的参数在用“逗号”结尾并按照相同的顺序。 所以附带一份最终结果的一般形式应该是这样的:

("this is a quoted {} string with {} tokens {} in it", arg1, arg2, arg); 
+1

你的第一个例子看起来不对;它不包含'{}'。 – melpomene

+0

使用':perldo'的解决方案是否可以接受? – melpomene

+1

如果有人找到一种方法来做到这一点真的很棒:D –

回答

1

最简单的方法是做它在多个步骤。以下方法中所需的步骤数量等于任何单个调试语句中的最大参数数量加上一个。

示例文本文件:

debug("some random text: val " + arg1); 
debug("some random text: val " + arg1 + " val2 " + arg2); 
debug("some random text: val " + getValue(1) + " val2" + getValue(2) + "."); 

我们开始通过追加必要的空字符串字面哪里。

:g/^\s*debug("/s/[^"[:blank:]]\s*\zs\ze);/ + ""/ 

请注意第1行和第2行如何受影响,但第3行不受影响。这是故意的;第3行已经以字符串文字结尾。

debug("some random text: val " + arg1 + ""); 
debug("some random text: val " + arg1 + " val2 " + arg2 + ""); 
debug("some random text: val " + getValue(1) + " val2" + getValue(2) + "."); 

接下来,我们移动每个第一个参数的位置。

:g/^\s*debug("/s/"\s*+\([^+]\{-}\)\s*\(+\s*"\(.*\)\)\?\ze);/{}\3,\1/ 

请注意第二个(和以下)参数如何不受影响。

debug("some random text: val {}", arg1); 
debug("some random text: val {} val2 " + arg2 + "", arg1); 
debug("some random text: val {} val2" + getValue(2) + ".", getValue(1)); 

重复相同的命令。要做到这一点最简单的方法是按@:

debug("some random text: val {}", arg1); 
debug("some random text: val {} val2 {}", arg1, arg2); 
debug("some random text: val {} val2{}.", getValue(1), getValue(2)); 

不断重复的线路有两个以上的参数。一旦命令不再影响任何线路,就完成了。

注:

  • 我每调试语句(包括所有参数)占据一行的假设下做出此。
  • 使用的正则表达式可能需要对更复杂的参数表达式进行一些调整(例如,表达式本身包含+运算符)。
  • 建议您以后使用diff工具手动验证结果。
+0

很酷,我从来不知道'@:',谢谢!当然,在第一次之后它变得更加容易,因为你可以使用'@@'。 – BobH

+0

像冠军一样工作! – Oyunokata

0

对于一个相对“封闭”的解决方案(你仍然需要执行多个参数的命令多次),直到没有更多的变化重复此命令:

(例如,对于单行) :

:s/\([^"]*"[^"]*\)"\s*+\s*\([^ ,]\+\)\(\s*+\s*"\)\=\(\([^"]*\)"\)\=\(.*\)\([^"]*\));/\1{}\5"\6, \2\7);/ 

说明:
表达打破了代码分解成以下九个要素,包括7个括号中的元素(\1,...,\7,由开口括号内)和两个非括号的那些的顺序标识(列示如下--):

/\([^"]*"[^"]*\)"\s*+\s*\([^ ,]\+\)\(\s*+\s*"\)\=\(\([^"]*\)"\)\=\(.*\)\([^"]*\));/ 
    ----\1-----   --\2--- ---\3---  -\5--   \6 -\7--               
                ----\4---- 

\1: [^"]*"[^"]\* " Up to second quote (i.e. up to first closing quote) 
--: "\s*+\s*  " The first closing quote and '+' operator 
\2: [^ ,]\+   " The first concatenated arg (to be converted into an argument list element) 
\3: \s*+\s*"  " The following '+' operator and opening quote of the second string (if present) - discard 
\4: \([^"]*\)"  " The second string (if present), so we can close the quotes on our (newly combined?) first string 
\5:     " (Embedded in \4 above) - the second string minus the closing quote (the part we want) 
\6: .*    " Everything up to the final quote (if there are any more); no more quotes after this 
\7: [^"]*   " Everything else (up to closing paren) 
--:);    " The end 

和元素或子元素列为“如果存在的话”等与\=合格。我们用\1,\2(在其新位置),\5,\6\7建立我们想要的结果。

在开始添加范围或符合条件的图案,在@范尼的回答同时做多行(我倾向于只使用范围%,如:%s///整个文件,但可以匹配一些意想不到的线也)。

都是一样的告诫是@Ruud提到这里也适用 - 假定在一行中每个语句,可能不会考虑在参数更复杂的表达式,等

表达式像这是一个可怕的很多工作相比于说多步骤或脚本化的方法来提出和调试,但它确实是一个有趣的练习=)。