2013-10-10 40 views
2

我有一個日誌,我想在正則表達式匹配文本中應用替換。使用sed只替換正則表達式子字符串

實例,藉此日誌行:

date machine text random text and yet more random text - status code 

我想Ø由_更換所有空間文本區域內,無需更換日誌中的所有其他空間。輸出會是這樣:

date machine text_random_text_and_yet_more_random_text - status code 

要匹配我要替換的區域,我有這個正則表達式:

/machine \(.*\) -/

由於文字不規範,我可以有一個空間20,所以其很難直接匹配它,所以我匹配子字符串的開始和結束。

嘗試使用它我想這:

sed `/machine \(.*\) -/ s/ /_/g ' logfile 

但當然,它會取代所有的空格在日誌中,而不僅僅是匹配的子字符串。

我設法使用awk做到這一點,通過迭代和打印每個字段,直到我找到machine,在那裏我改變OFS="_",當我找到-其恢復到空間。它的工作......但是,我很好奇,如果這是可以解決使用sed。

感謝

+1

我不知道是什麼sed的支持時,它涉及少數 '高級' 正則表達式語法,但用PCRE,你可以像[那](http://regex101.com/r/sW0uM7)。 – Jerry

+0

Sed沒有PCRE,但這是一個有趣的網站!謝謝! – higuita

回答

1

這可能會爲你工作(GNU SED):

sed -r 's/(\S+\s+){2}/&\n/;s/\s+-/\n&/;h;y/ /_/;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/' file 
+0

謝謝,這個工程和使用sed!我試圖插入換行符來打破日誌,但在我的嘗試中,我需要幾個sed命令,並且感覺不對。你的解決方案看起來很完美 – higuita

0

這是一個GNU的awk命令來解決這個問題:

s='date machine text random text and yet more random text - status code' 
awk '{gsub(/ /, "_", $2); print $1 " machine " $2 " - " $3}' FS='machine *| *- *' <<<"$s" 

date machine text_random_text_and_yet_more_random_text - status code 
1

因爲有你喜歡用下劃線和空間文本前兩個空間 - 空間後,你可以這樣做這樣的:

awk -F " | - " '/machine/ {gsub(/ /,"_",$2)}1' file 
date machine text_random_text_and_yet_more_random_text status code 
+0

那個'} 1'對我來說是未知的......你能解釋它嗎,還是指向我一些文檔?我甚至不知道如何在谷歌搜索! :)我可以看到它打印的行,但更改爲0以外的數量做同樣的事情。 – higuita

+0

'1'確實意味着打印任何行。它總是如此,所以它會執行默認操作,打印。它可以像這樣寫成'1 {print $ 0}'。所以這個'awk'將會改變'$ 2'字段的值,當它的'machine',然後'1'確實打印所有的行,包括修改後的行。 – Jotne

0

另一個awk的解決方案可能是:

awk '{ 
    # Capture the stringpart in `a`rray 
    match($0,"machine (.*) -",a) 
    # Make the changes 
    gsub(" ","_",a[1]) 
    print gensub("machine (.*) -","machine " a[1] " -","g") 
}' INPUTFILE 
0

的Perl:

echo "date machine text random text and yet more random text - status code" | 
perl -pe 's/(?<=machine )(.*)(?= -)/ ($repl = $1) =~ s{\s}{_}g; $repl /e' 
date machine text_random_text_and_yet_more_random_text - status code