有兩個部分所需要的詭計:當你達到一個接近括號(但這樣做反覆上線)
停止更換:
s/\(\[[^] ]*\) /\1_/g
此相匹配的開括號,後面的零個或多個字符既不是一個空白,也不是接近方形支架。全局後綴意味着該模式適用於所有以開放方括號開始的序列,最後是行上的空白或近方括號。還要注意,這個正則表達式不會改變'[single-word] and context
',而原始文件會將其轉換爲'[single-word]_and context
',這不是練習的目標。
讓sed從這個地方開始重複搜索。不幸的是,沒有一個真正的好方法來做到這一點。 Sed總是在被取代的文本之後繼續搜索;這是我們不想要的一次。有時候,您可以簡單地重複替代操作。在這種情況下,每次替換成功時都必須重複它,當沒有替換時停止。
在sed
不爲人知的操作中的兩個是「:label
」和「t
」命令。不過,它們出現在Unix的第七版(大約1978年)中,所以它們不是新功能。首先簡單地識別腳本中的一個位置,這可以用「b
」(這裏未想)或「t
‘被跳樓:到’:
」功能的軸承,如果任何替換標籤
[2addr]t [label]
分公司自從最近讀取輸入行或執行't
'函數以來已經做出。如果沒有指定標籤,則分支到腳本的末尾。
奇妙:我們需要:
sed -e ':redo; s/\(\[[^] ]*\) /\1_/g; t redo' data.file
除 - 它不工作,都在這樣的一條線(至少不是在MacOS X)。這也令人欽佩的工作,雖然:
sed -e ':redo
s/\(\[[^] ]*\) /\1_/g
t redo' data.file
或者,正如在評論中指出,你可以寫三個獨立的 '-e' 選項(在MacOS X的工作原理):
sed -e ':redo' -e 's/\(\[[^] ]*\) /\1_/g' -e 't redo' data.file
鑑於數據文件:
a line with [one blank] word inside square brackets.
a line with [two blank] or [three blank] words inside square brackets.
a line with [no-blank] word inside square brackets.
a line with [multiple words in a single bracket] inside square brackets.
a line with [multiple words in a single bracket] [several times on one line]
從所示的sed腳本輸出爲:
a line with [one_blank] word inside square brackets.
a line with [two_blank] or [three_blank] words inside square brackets.
a line with [no-blank] word inside square brackets.
a line with [multiple_words_in_a_single_bracket] inside square brackets.
a line with [multiple_words_in_a_single_bracket] [several_times_on_one_line]
最後,如果你只需要在每一行的第一個方括號字段中完成這個問題,那麼我們需要確保在開始匹配之前沒有空的方括號。這種變體的工作原理:
sed -e ':redo' -e 's/^\([^]]*\[[^] ]*\) /\1_/' -e 't redo' data.file
(在「G」限定符不見了 - 它可能不需要在其他變體要麼給出的循環;它的存在可能使過程稍微更有效,但它很可能會基本上不可能檢測到該圖案現在錨定到該行的開頭(脫字符)並且包含零個或多個在第一個開放方括號之前未打開方括號的字符)。
Sample output:
a line with [two_blank] or [three blank] words inside square brackets.
a line with [no-blank] word inside square brackets.
a line with [multiple_words_in_a_single_bracket] inside square brackets.
a line with [multiple_words_in_a_single_bracket] [several times on one line]
啊,聰明地觀察到`[a b c]`在第一個子之後變成`[a_b c]`,因此可以遞歸處理。我正在考慮將'[stuff]`分成一個單獨的行,'這些行,然後重新加入。 – 2010-12-21 21:43:17
+1。它是否在OS X上執行此操作:'sed -e':redo'-e's/\(\ [[^]] * \)/ \ 1_/g'-e't redo'`而不是打破它在多條線上? – 2010-12-22 02:03:25