2017-05-29 329 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