我想替换(整个字符串)
$(TOPDIR)/$(OSSCHEMASDIRNAME)
和
/udir/makesh/$(OSSCHEMASDIRNAME)
我试过了
perl -pi.bak -e "s/\$\(TOPDIR\)\/\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\$\(OSSCHEMASDIRNAME\)/g " makefile
但我得到了无与伦比的括号错误
您必须“加倍”转义美元符号。像这样:
echo "\$(TOPDIR)/\$(OSSCHEMASDIRNAME)" | perl -p -e "s/\\$\(TOPDIR\)\/\\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\\$\(OSSCHEMASDIRNAME\)/g"
首先,您不需要使用/
正则表达式。他们只是规范的。你几乎可以使用任何东西。因此,您的代码可以变成(简化一些\
):
perl -pi.bak -e "s|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g " makefile
现在要实际解决您的问题,因为您使用的是"
代替'
,所以外壳会尝试找出什么$\
意思,然后将其替换为(大概)什么都没有。所以你真正想要的是:
perl -p -i.bak -e 's|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g' makefile
当对转义有疑问时,您可以简单地使用quotemeta
or \Q ... \E
。
perl -pe 's#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;'
请注意使用前瞻断言来避免我们在替换中重复尾随部分的麻烦。
quotemeta
解决方案类似于:
perl -pe 'BEGIN { $dir = quotemeta(q#$(TOPDIR)/$(OSSCHEMASDIRNAME)#); }
s#$dir#/udir/makesh/$(OSSCHEMASDIRNAME)#;'
当然,您不需要使用实际的单线。当 shell 引用引起麻烦时,最简单的选择是为您的脚本编写一个小源文件:
s#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;
并运行:
perl -p source.pl inputfile