我有一个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}
只需即插即用,即可捕获您想要的群组。