2017-05-29 58 views
0

我試圖用sed來替換文件中的某些字符串,並且遇到了一個問題。sed:替換部分正則表達式並保留前綴/後綴

我有以下字符串:

TEMPLATE_MODULE 
TEMPLATE_SOME_ERR 
TEMPLATE_MORE_ERR 

我想更換TEMPLATE_MODULE一些字符串,並與模板開始和ERR結束與一個不同的字符串的所有字符串,如下:

TEMPLATE_MODULE ---> NEW_MODULE_NAME 
TEMPLATE_SOME_ERR ---> NEW_MODULE_NAME_SOME_ERR 
TEMPLATE_MORE_ERR ---> NEW_MODULE_NAME_MORE_ERR 

更換TEMPLATE_MODULE的很簡單:

find . -type f -print -exec sed -i "s/TEMPLATE_MODULE/NEW_MODULE_NAME/g" {} + 

雖然我不知道如何處理其他部分。如果我尋找以TEMPLATE_ *開頭的字符串,我還會捕獲TEMPLATE_MODULE

我也想保持SOME_ERRMORE_ERR後綴所以這個解決方案是行不通的:

find . -type f -print -exec sed -i "s/TEMPLATE_.*_ERR$/NEW_MODULE_NAME/g" {} + 

任何想法? 謝謝!

+0

你有GNU sed的?輸出'sed --version'? – Inian

+0

請注意'。*'是一個正則表達式全局匹配,而不是普通的glob擴展。您需要啓用'-r'來支持它,它只在'GNU sed'中可用 – Inian

+0

我正在使用GNU sed 4.2.2 – Vardit

回答

1

考慮這個樣品輸入

$ cat ip.txt 
foo 
TEMPLATE_MODULE 
TEMPLATE_SOME_ERR 
TEMPLATE_MORE_ERR 
TEMPLATE_SOME_ERR xyz 

使用多個s命令和捕捉組

$ sed -E 's/\bTEMPLATE_MODULE\b/NEW_MODULE_NAME/g; s/\bTEMPLATE\w*(_(SOME|MORE)_ERR)\b/NEW_MODULE_NAME\1/g' ip.txt 
foo 
NEW_MODULE_NAME 
NEW_MODULE_NAME_SOME_ERR 
NEW_MODULE_NAME_MORE_ERR 
NEW_MODULE_NAME_SOME_ERR xyz 
  • \b是單詞邊界。 \bcat\b只會匹配cat並不會匹配scatcater
  • s/\bTEMPLATE_MODULE\b/NEW_MODULE_NAME/g將取代TEMPLATE_MODULENEW_MODULE_NAME
  • s/\bTEMPLATE\w*(_(SOME|MORE)_ERR)\b/NEW_MODULE_NAME\1/g將取代然後用_SOME_ERR_MORE_ERRNEW_MODULE_NAME結束零個或多個單詞字符和字符串捕獲
  • TEMPLATE解決方案適用於GNU sed,不確定其他實現的可移植性
+0

謝謝! '\ 1'是什麼意思? – Vardit

+1

@Vardit將擁有捕獲的組..請參閱https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions – Sundeep

0

假設「TEMPLATE_MODULE」和「TEMPLATE_」是文字,但「SOME_ERR」和「MORE_ERR」是佔位符,以下內容似乎是可能的。

sed "s/TEMPLATE\(_MODULE\)*/NEW_MODULE_NAME/" 

我推薦把它當作裸露的sed行來使用,如果可以的話,將它集成到命令行中。

我認爲這段代碼並沒有比你自己的代碼對事件和拼寫做出更多的假設。
但是,您可能想要使用「錨定」,以免意外替換「SOMEOTHERTEMPLATE_」等。

要開始,你就關在這裏是一個修改版本:

sed "s/\bTEMPLATE\(_MODULE\)*/NEW_MODULE_NAME/" 

我建議嘗試與:

TEMPLATE_MODULE 
TEMPLATE_SOME_ERR 
TEMPLATE_MORE_ERR 
OTHER_TEMPLATE_MODULE 
OTHER_TEMPLATE_SOME_ERR