我在sed
脚本中替换了以下bash
扩展正则表达式:
sed -i.bak -E 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_]+}{\\input{([[:alnum:]_\/]+)}}{}~\\input{\1}~' file.txt
应该替换像
这样的字符串\iftoggle{xx_yy}{\input{xx_yy/zz}}{}
带
\input{xx_yy/zz}
在file.txt
内。
这在OS X
本地工作得很好,但脚本需要是POSIX。具体来说,它在我的远程Travis CI
版本(使用Linux
)上失败。虽然sed -E
没有记录GNU sed
,但它的行为与sed -r
类似,似乎工作正常,允许带有扩展正则表达式的sed的POSIX版本。
给出的错误是:
sed: -e expression #1, char 81: Invalid content of \{\}
我也不确定错误从何处开始计算字符,是否是行的开头,还是仅包含在引号(表达式)中的部分?
答案 0 :(得分:3)
这里你不需要ERE。使用BRE:
sed i.bak 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_][[:alnum:]_]*}{\\input{\([[:alnum:]_\/][[:alnum:]_\/]*\)}}{}~\\input{\1}~' file.txt
{
不需要在此处进行转义,(
即可。
由于+
不属于BRE,您可以将[[:alnum:]_]+
替换为[[:alnum:]_][[:alnum:]_]*
或[[:alnum:]_]\{1,\}
。
作为旁注,\+
可以与BRE中的GNU sed一起使用,但要记住它不是可移植的,它是GNU扩展。
答案 1 :(得分:1)
这不是直接回答
sed
的问题,而是在perl
命令行正则表达式搜索和替换中提供了另一种更简单的方法。
perl -p -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)\}\}\{\}|\input\{\2/\3\}|g' file
\input{xx_yy/zz}
将字词分隔符用作|
和\w+
以匹配[[:alnum:]]
个字符。
对于就地替换,请使用与-i
sed
标记
perl -p -i.bak -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)\}\}\{\}|\input\{\2/\3\}|g' file
关于Word-characters(\w)
in perl POSIX
个字符类页面,
单词字符
A \ w匹配单个字母数字字符(字母字符或十进制数字);或连接标点字符,例如下划线(“_”);或者是一个附加在其中一个上面的“标记”字符(如某种口音)。它与整个单词不匹配。要匹配整个单词,请使用\ w +。这与匹配英文单词不同,但在ASCII范围内,它与Perl标识符字符串相同。
对于输入 - 在input
内有多个文件夹,例如
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}
只需插入和播放所需的群组即可。