正则表达式中无法匹配的括号 - Linux

时间:2012-05-14 09:06:35

标签: regex linux perl

我想替换(整个字符串)

    $(TOPDIR)/$(OSSCHEMASDIRNAME)

    /udir/makesh/$(OSSCHEMASDIRNAME)
<{3>}

中的

我试过

     perl -pi.bak -e "s/\$\(TOPDIR\)\/\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\$\(OSSCHEMASDIRNAME\)/g " makefile

但是我得到了无法匹配的括号错误

3 个答案:

答案 0 :(得分:2)

你必须“加倍”逃脱美元符号。像这样:

echo "\$(TOPDIR)/\$(OSSCHEMASDIRNAME)" | perl -p -e "s/\\$\(TOPDIR\)\/\\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\\$\(OSSCHEMASDIRNAME\)/g"

答案 1 :(得分:2)

首先,您不需要将/用于正则表达式。他们只是规范的。你几乎可以使用任何东西。因此,您的代码可以变为(简化一些\):

perl -pi.bak -e "s|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g " makefile

现在要实际解决您的问题,因为您使用的是"而不是',shell会尝试找出$\意味着什么然后替换为(推测)什么都没有。所以你真正想要的是:

perl -p -i.bak -e 's|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g' makefile

答案 2 :(得分:1)

如果对转义有疑问,您只需使用quotemeta\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