2013-09-27 208 views
6

我需要使用*符號突出顯示文本中的每個重複單詞。
例如使用sed多次執行同一行上的命令

lol foo lol bar foo bar 

應該

lol foo *lol* bar *foo* *bar* 

我試着用下面的命令:

echo "lol foo lol bar foo bar" | sed -r -e 's/(\b[a-zA-Z]+\b)([^*]+)(\1)/\1\2*\3*/' 

它給我:

lol foo *lol* bar foo bar 

然後我說g標誌:

lol foo *lol* bar foo *bar* 

foo並不突出。
我知道這是因爲seddoesn't look behind if the match was found

我可以只用sed嗎?

+1

只有'sed'你說...這需要一些我相信的'sed'魔法。 – rid

+0

爲什麼不使用'awk'?它可以解決你的問題。 – Jotne

+0

@Jotne坦率地說,我已經完成了只有sed才能完成的任務。但總的來說,我感興趣的是,如果'sed'可以在一行上執行相同的命令多次 – Dany

回答

4

Sed不是此任務的最佳工具。它看起來並不超前,看看隱藏和非貪婪的量詞,但給一個嘗試下面的命令:

sed -r -e ':a ; s/\b([a-zA-Z]+)\b(.*) (\1)(|$)/\1\2 *\3*/; ta' 

它使用條件分支,直到它無法執行替換命令。另外,你不能檢查([^*]+),因爲第二輪它必須經過一些*的第一個替代,你的選擇是貪婪.*。最後,你不能匹配(\1),因爲它會一次又一次匹配第一個字符串lol。您需要一些環境,如空間或行尾。

該命令產生:

lol foo *lol* bar *foo* *bar* 

UPDATE:由potong在給予的改進:

sed -r ':a;s/\b(([[:alpha:]]+)\s.*\s)\2\b/\1*\2*/;ta' file 
+0

+1輝煌......那就是魔術! – iamauser

+0

@Birei是的,這是神奇的,它適合我! 你能解釋一下在這種情況下'a'和'ta'命令的作用嗎? – Dany

+0

稍有改進(因爲這個解決方案可能在最後一個詞是重複時在行末引入額外空間)是:'sed -r':a; s/\ b(([[:alpha:]] +)\ s。* \ s)\ 2 \ b \ \ 1 * \ 2 * /; ta'文件'。注:如果你在'ta'命令之前插入'l0'命令,你會看到sed做它的魔力。 – potong

1

使用awk

awk '{for (i=1;i<=NF;i++) if (a[$i]++>=1) printf "*%s* ",$i; else printf "%s ",$i; print ""}' file 
lol foo *lol* bar *foo* *bar*