2012-11-08 52 views
0

我想找到Vim的一個好辦法做到這一點搜索和替換以下 -匹配模式,然後替換使用模式

name_1 
end 
name_2 
end 

name_3 
end 

,我拿名_「x」和其追加到它的在「結束」聲明之後。因此,它應該是這樣的 -

name_1 
end_name_1 
name_2 
end_name_2 
name_3 

end_name_3 

注 - 空行NAME_3遺址「name_x」和「結束」之間的恆定線前間距。所以,我在想是這樣

:g/\(name_x\)/,/end/ s/end/end_\1/ 

現在不工作嘗試存儲這樣的第一圖案,但希望你的想法。這裏有什麼竅門?

感謝

回答

3

您遇到的問題是,\1指的是當前替代的匹配組不:g命令的模式。可悲的是,您無法訪問之前搜索的以前的匹配組。然而有一些方法可以實現你的目標。我會建議的第一個是宏。

首先在非匹配線上開始。這可以通過在文件頂部插入空白行來完成(如果需要的話)。

  1. 開始爲你的格局宏搜索:/name_\d\+
  2. 抽出,直到你的方式結束:y//e
  3. 找到結束模式:/end/e
  4. 插入一個下劃線a_
  5. p
  6. 結束您的宏q
  7. 執行大量的宏。例如[email protected]

這裏是我使用的宏:

:let @q = "/name_\\d\\+\<cr>y//e\<cr>/end/e\<cr>a_\<esc>p" 

另一種方法是用類似的方式來使用:global命令添加到您的嘗試。

:g/name_\d\+/let @@=matchstr(getline('.'),'name_\d\+')|/end/s//\=submatch(0).'_'[email protected]@/ 

我個人認爲這太複雜了,但很高興有選擇。該命令可以被分解成以下部分:

  • :g/name_\d\+每行匹配名_和一些數
  • getline('.')執行一個命令將返回當前行的字符串
  • matchstr(getline('.'), 'name_\d\+')將只返回匹配的當前行
  • let @@ = matchstr(...)將設置匹配部向缺省的一部分寄存器
  • /end/s/將在以下林執行:s e匹配end
  • s//\=.../匹配上次使用的模式,並用快速替換它。
  • submatch(0).'_'[email protected]@用整個匹配模式創建一個字符串,後跟一個下劃線和未命名寄存器的內容。

欲瞭解更多有關以下主題看:

:h q 
:h search-offset 
:h :g 
:h :[email protected] 
:h registers 
:h matchstr(
:h getline(
:h range 
:h submatch(
+0

感謝很多答案。這非常有幫助。我總是傾向於在宏之前使用全局命令subs,對於這種情況來說,宏看起來確實是一條路。但我會研究你給出的命令故障。 – itchmyback

+0

彼得同時使用':global'和一個宏:':g'用於定義要在其上執行操作的行以及用於執行該操作的宏。 ':global'和宏是爲對方而設的。 – romainl

+0

Romainl你是對的,他們非常得心應手。我個人更喜歡':g'加上':norm',但這個想法非常相似。也許我應該添加下面的解決方案:'g/name_ \ d \ +/norm y/name_ \ d \ +/e^M/end/e^Ma _ ^] p'。思考?不過,我確實認爲我可能會假定線條開始時沒有任何領先的空白區域。 –