2016-07-14 16 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提到這裏也適用 - 假定在一行中每個語句,可能不會考慮在參數更復雜的表達式,等

表達式像這是一個可怕的很多工作相比於說多步驟或腳本化的方法來提出和調試,但它確實是一個有趣的練習=)。