为什么sed在linux上提供一个“无效内容”错误,而不是在Mac上

我有一个bash脚本里面的sed扩展正则expression式replace:

 sed -i.bak -E 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_]+}{\\input{([[:alnum:]_\/]+)}}{}~\\input{\1}~' file.txt 

这应该取代像string

 \iftoggle{xx_yy}{\input{xx_yy/zz}}{} 

 \input{xx_yy/zz} 

file.txt里面。

OS X ,这在本地很好,但脚本需要是POSIX。 具体来说,它失败了我的远程Travis CI构build(使用Linux )。 虽然sed -E没有logging在GNU sed ,但它的行为与sed -r类似,并且似乎工作正常,允许使用扩展正则expression式的sed的POSIX版本。

给出的错误是:

 sed: -e expression #1, char 81: Invalid content of \{\} 

我也不确定错误是从哪里开始计算的,不pipe是行首,还是只有引号(expression式)的部分?

这里你不需要ERE。 使用BRE:

 sed i.bak 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_][[:alnum:]_]*}{\\input{\([[:alnum:]_\/][[:alnum:]_\/]*\)}}{}~\\input{\1}~' file.txt 

{不需要在这里逃跑,但(做。

As +不是BRE的一部分,您可以用[[:alnum:]_]+[[:alnum:]_]\{1,\}替换[[:alnum:]_]\{1,\}

另外, \+可以和BRE的GNU sed一起使用,但请记住它不是可移植的,它是一个GNU扩展。

这不直接回答sed的问题,但提供了一个更简单的方法来做到这一点在perl命令行正则表达式的搜索和替换。

 perl -p -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)\}\}\{\}|\input\{\2/\3\}|g' file \input{xx_yy/zz} 

使用字词分隔符作为|\w+匹配[[:alnum:]]字符。

对于in-place替换,使用类似于sed-i标志

 perl -p -i.bak -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)\}\}\{\}|\input\{\2/\3\}|g' file 

关于perl POSIX字符类页面中Word-characters(\w)

单词字符

A \ w匹配单个字母数字字符(一个字母字符或一个十进制数字); 或连接标点符号(如下划线(“_”); 或附加到其中之一的“标记”字符(如某种口音)。 它不匹配整个词。 要匹配整个单词,请使用\ w +。 这与匹配一个英文单词不是一回事,但在ASCII范围内它与一串Perl-identifier字符相同。

对于输入内有多个文件夹,例如

 cat file \iftoggle{xx_yy}{\input{xx_yy/zz_yy_zz_kk/dude_hjgk}}{} perl -p -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)/(\w+)\}\}\{\}|\input\{\2/\3/\4\}|g' file \input{xx_yy/zz_yy_zz_kk/dude_hjgk} 

只需即插即用,即可捕获您想要的群组。