2012-03-26 28 views
2

我想在不使用它們的代碼中使用製表符。我所做的到現在爲止實施的標籤是相當handcrafty:用它的次數替換字數

%s/^ /\t/g 
%s/^\t /\t\t/g 
.. 

問:有沒有辦法通過標籤來代替兩個空格()(\t)的次數,發現之初一條線?

+2

這不工作? ':%s// \ t/g'? – 2012-03-26 10:24:34

+2

您也可以使用':retab'命令。說':set ts = 2 noet'然後':retab!'。然後將tabstop重置爲您要使用的值,例如。 ':set ts = 4' – glts 2012-03-26 10:46:33

+0

@glts:我會輸入這個評論作爲回答得到代表(因爲這正是OP想要的)! – eckes 2012-03-26 11:00:17

回答

3

有(至少)三種替代技術與這種情況有關。

第一個利用前面的原子匹配語法來自然地定義一個縮進步驟。根據問題聲明, 縮進步驟是一對相鄰的空格字符,前面沒有空格 但是從行首開始爲空格。按照此定義,可以從右到左構造實際的替代模式。

:%s/\%(^ *\)\@<= /\t/g 

實際上,圖案指定的以下零寬度\@<=匹配前述原子,其是包裝在分組中的 圖案^ *括號\%(/\)兩個字面空格字符 的發生。這些非捕獲的 括號用於代替通常捕獲的括號,\(/\),因爲 不需要進一步提及匹配的前導空格。由於g 標誌,上述:substitute命令通過 對的前導空格對運行,並用單個製表符替換它們中的每一個。

第二種技術採用不同的方法。可以將每個以空格字符 開頭的行分成兩個:一個包含原始行的縮進空間,另一個包含其餘部分,而不是匹配單獨的 縮進級別。之後,可以直接替換第一行上的所有空格對,並將 連接在一起。

:g/^ /s/^ \+/&\r/|-s/ /\t/g|j! 

第三個想法是Vim的腳本語言 手段來處理前導空格。一種便捷的方法是使用:substitute命令的 表達式功能(請參閱:help sub-replace-\=)。 用\=凝視指令的替代字符串,可以將 替換成\=後指定的表達式 的評估結果 。

:%s#^ \+#\=repeat("\t",len(submatch(0))/2) 
+0

一些解釋的話?謝謝! – ezdazuzena 2012-03-27 08:17:27

+0

想到更多的是什麼'\%','\ @<='和這樣的東西代表。我真的很想從你的答案中學習,而不僅僅是複製和粘貼它。謝謝! – ezdazuzena 2012-03-27 10:29:15

+0

還有一點意見:感謝! +1並正確 – ezdazuzena 2012-03-27 14:22:12

3

如果您特別想在空行處將空格轉換爲製表符(或反之亦然),那麼有用的:retab命令會照顧到這一點。例如:

  • :retab! 2將轉換的空間中的兩組突舌
  • :set expandtab然後:retab! 2將(寬度2)製表位轉換回空間

參見:h :retab(和:h 'ts'),用於細節。

這不是原始問題的一般解決方案,但我認爲它涵蓋了最常見的用例。

+1

@gits:正如在我的問題的評論中所述:這將改變所有標籤爲空格。這不是我想要的。 – ezdazuzena 2012-03-26 12:49:48

+0

你說得對。我現在看到你的問題。現在我很好奇,看到一個工作的解決方案,太... – glts 2012-03-26 13:39:09

+0

@glts:看看我的[答案](http://stackoverflow.com/a/9885445/254635)中列出的命令。 – 2012-03-27 08:37:48

0

沒有通用的方法來使用:正則表達式。您無法使/g修飾符向後看,否則它將無法使用,並且無法可靠地檢查您是否在行的開頭而不向後看。

通常這樣做的唯一方法是進行循環,像這樣:

:for i in range(100) 
: %s/^\t*\zs /\t/e 
:endfor 

這是醜陋的,緩慢的,高度不推薦的。使用:retab

+1

謝謝,但如前所述,retab不是一個好選擇,因爲它會影響文件中的所有選項卡。 – ezdazuzena 2012-03-26 13:32:56

+0

如果retab不是您想要的,請使用我提供的for循環替換。正如我所解釋的那樣,這是真正的唯一方法,可以僅替換行首的字符。 – 2012-03-26 14:28:45