2010-10-05 20 views
51

我經常使用文本文件,它有不同數量的空格作爲單詞分隔符(像Word這樣的文本處理程序可以執行此操作,因爲字母大小不同,可以公平分配空白量某些字體,即使在保存爲純文本的情況下,它們也會將這些令人討厭的可變數量的空格)。vim正則表達式替換多個連續的空格只有一個空格

我想自動化替換具有單個空格的可變長度的空白序列的過程。我懷疑一個正則表達式可以做到這一點,但在段落開頭(通常是其中的四個,但並非總是),也有空格,我想讓它保持不變,所以基本上我的正則表達式也不應該觸及領先的空格,增加了複雜性。

我使用的是vim,因此如果這是可行的,vim正則表達式中的正則表達式對我來說是非常有用的。

我目前的進展是這樣的:

:%s/ \+/ /g 

,但它不能正常工作。

我還在考慮編寫一個vim腳本,它可以逐個解析文本行,通過char處理每行char並在第一行之後跳過空白處,但是我有一種感覺這會是矯枉過正。

+0

很好的重新格式化垂直對齊的代碼:) – JackHasaKeyboard 2016-08-07 22:06:23

回答

31

添加\+前一個額外的空間在實用主義的利益,我傾向於只是做作爲一個三階段的過程:

:g/^ /s//XYZZYPARA/g 
:g/ \+/s// /g 
:g/^XYZZYPARA/s// /g 

我不懷疑,可能有一個bette (也許使用宏或者甚至是一個純正則表達式的方式),但是當我匆忙時,我通常會發現它有效。當然,如果您有從XYZZYPARA行,你可能需要調整字符串:-)

這是不夠好,轉:

This is a new paragraph 
spanning  two lines. 
    And so is this but on one line. 

到:

This is a new paragraph 
spanning two lines. 
    And so is this but on one line. 

另存爲:如果您想知道爲什麼我使用:g而不是:s,這只是習慣。 :g可以做任何事情:s可以和更多。這實際上是一種在所選行上執行任意命令的方法。在這種情況下,要執行的命令恰好爲s,所以沒有實際區別,但是,如果您想成爲vi高級用戶,則應該在某個時刻查看:g

+2

是的,很久以前,我的純粹主義者/理想主義者開始退後一步。現在我只想完成這項工作,尤其是如果替代方案是600字符的正則表達式,帶有後退跟蹤和前瞻性,那麼當我必須在三個月內回來調試時,我不會明白:-) – paxdiablo 2010-10-05 03:12:25

+0

+1 xyzzy珩磨機 – SingleNegationElimination 2010-10-05 03:56:04

+0

我在上面使用了一個變體: :g/\ +/s ///g 我理解空間和\匹配一個或多個,不知道/ s /所做的是什麼,誰知道? – anteatersa 2012-11-28 11:47:42

80

這將取代2個或多個空格

s/ \{2,}/ /g 

,或者你可以到你的版本

s/ \+/ /g 
+7

我認爲這可能是最好和最簡單的答案。它還具有在其他RegEx方言中工作的額外好處! – TrinitronX 2012-07-16 16:27:57

+0

這絕對是最好也是最簡單的答案。 – RubyFanatic 2017-12-21 20:29:59

2

這是行得通嗎?

%s/\([^ ]\) */\1 /g 
+0

' ) – Benoit 2010-10-05 16:32:36

+0

啊!尼斯。我同意得更好。謝謝。 – frogstarr78 2010-10-06 23:23:52

55

這將這樣的伎倆:

%s![^ ]\zs \+! !g 

許多置換可以在Vim中進行比使用\zs\ze元序列以外的正則表達式方言更容易。他們所做的是從最終結果中排除部分匹配,或者序列前的部分(\zs,「s」代表「此處開始」)或後面的部分(\ze,「e」代表「結束於此」)。在這種情況下,模式必須首先匹配一個非空格字符([^ ]),但以下\zs表示最終匹配結果(即將被替換的內容)在之後開始這個字符。

由於沒有辦法在行前導空白字符前面有非空格字符,所以它不會被模式匹配,所以替換不會替換它。簡單。

+1

我想提出這個方案:'%s!\ S \ @<= \ +! !g'。 '\ @<='是我喜歡使用它的一隻美麗的鴨子。另見':help/\ @<=' – Benoit 2010-10-05 16:36:40

+1

我更喜歡'zs'的小手指雜技,而不是用類似的方式輸入'@<='......(如果程度較低),我比V更喜歡Vim (花莖)M(ETA)A(LT)C(ONTROL)S(HIFT)。 :) OTOH,一個人的天賦感總是值得一些犧牲,所以感到自由。 – 2010-10-05 16:48:52

+0

取決於你正在使用的鍵盤佈局當然... – Benoit 2010-10-05 18:22:35

2

我喜歡這個版本 - 它類似於亞里士多德Pagaltzis的展望版本,但我覺得它更容易理解。 (也許只是我用\ ZS的不熟悉)

s/\([^ ]\) \+/\1 /g 

或所有空白

s/\(\S\)\s\+/\1 /g 

我把它讀作「代替一個空格,然後多個空格用的東西和其他東西所有出現單一空間「。

+0

當然,這個版本比類型更挑剔,並且在飛行中制定 - 這幾乎就像它得到的一樣微不足道。你會熟悉'\ zs'和'\ ze',他們可以對更復雜的模式的可寫性和可讀性做出奇蹟(特別是當你有理由同時使用這兩種模式!)。 – 2010-10-05 04:43:43

+0

我當然會看看'\ zs'和'\ ze',但我也經常在python和sed中使用我的正則表達式。因此,擁有可以跨多個應用程序工作的解決方案可能會很好。 – 2010-10-05 05:11:50

6

這裏有很多很好的答案(特別是亞里士多德的:\zs\ze是值得學習的)。只是爲了完整性,您也可以用負向後看斷言做到這一點:

:%s/\(^ *\)\@<! \{2,}/ /g 

這是說「找到2個或多個空格(' \{2,}')未通過「後跟零或行的開始之前更多空間'「。如果你喜歡減少反斜槓的數量,你也可以這樣做:

:%s/\v(^ *)@<! {2,}/ /g 

但它只會節省你兩個字符!如果您不介意執行冗餘更改(即將單個空間更改爲單個空間),您也可以使用' +'而不是' {2,}'

你也使用負向後看只是檢查一個非空格字符:

:%s/\S\@<!\s\+/ /g 

這是多(亞里士多德的略加修改的版本來治療空格和製表符一樣同樣爲了節省一點打字):

:%s/\S\zs \+/ /g 

參見:

:help \zs 
:help \ze 
:help \@<! 
:help zero-width 
:help \v 

和(閱讀全部!):

:help pattern.txt 
1

已回答;但儘管我會拋棄我的工作流程。

%s///g 
@:@:@:@:@:@:@:@:@:@:@:@:(repeat till clean) 

快速且簡單的記憶。上面有更優雅的解決方案;但只是我的.02。

+1

這不是一個好的解決方案:首先它會刪除問題的作者希望避免的主要空白。第二,你可以做100 @:運行100次寄存器的內容:(這是最後一個ex命令) – Benoit 2010-10-05 16:34:41

+1

因此我說這不是我答覆中的最佳答案:) – wom 2010-10-06 18:18:46

+2

我仍然覺得這個答案有用,儘管它確實有用沒有很好地回答OP的問題。 – 2015-02-09 23:44:20

相關問題