Regex 为什么sed提供了一个;无效内容“;linux上出现错误,但mac上没有

Regex 为什么sed提供了一个;无效内容“;linux上出现错误,但mac上没有,regex,linux,bash,macos,sed,Regex,Linux,Bash,Macos,Sed,我在bash脚本中有以下sed扩展正则表达式替换: sed -i.bak -E 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_]+}{\\input{([[:alnum:]_\/]+)}}{}~\\input{\1}~' file.txt 它应该替换字符串,比如 \iftoggle{xx_yy}{\input{xx_yy/zz}}{} 与 内部file.txt 这在OSX上的本地工作正常,但脚本需要是POSIX。具体来说,它在我的远程traviscibuild(

我在
bash
脚本中有以下
sed
扩展正则表达式替换:

sed -i.bak -E 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_]+}{\\input{([[:alnum:]_\/]+)}}{}~\\input{\1}~' file.txt
它应该替换字符串,比如

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

内部
file.txt

这在
OSX
上的本地工作正常,但脚本需要是POSIX。具体来说,它在我的远程
travisci
build(使用
Linux
)上失败。虽然
sed-E
没有为
gnused
编写文档,但它的行为与
sed-r
一样,似乎工作正常,允许使用带有扩展正则表达式的POSIX版本的sed

给出的错误是:

sed: -e expression #1, char 81: Invalid content of \{\}
我也不确定错误从何处开始计数字符,是从行的开头开始,还是仅仅是用引号括起来的部分(表达式)

这并没有直接用
sed
回答问题,而是在
perl
命令行regex搜索和替换中提供了另一种更简单的方法

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

对于就地更换,使用类似于sed的
-i
标志

perl -p -i.bak -e 's|\iftoggle\{(\w+)\}\{\\input\{(\w+)/(\w+)\}\}\{\}|\input\{\2/\3\}|g' file
关于字符类页面

文字字符

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}

只需按您需要的数量即插即用即可。

这里不需要您。使用BRE:

sed i.bak 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_][[:alnum:]_]*}{\\input{\([[:alnum:]_\/][[:alnum:]_\/]*\)}}{}~\\input{\1}~' file.txt
{
不需要在这里转义,但是
可以

由于
+
不是BRE的一部分,您可以用
[[:alnum:][uUnum:][uUnum:][uUnum:][:alnum:][uUnum:][uUnum]*
[:alnum:][uUnum:][1,\}
替换
[:alnum uUnum


作为旁注,
\+
可以与BRE中使用的GNU一起使用,但请记住它不是可移植的,它是GNU扩展。

在这里,
{}
用于指定类似于
{5}
的量词,以匹配前面的字符5次。因此它们必须转义以匹配文字
{}(代码)我怀疑它是如何在osx上工作的,所以我怀疑它是如何在osx上工作的,所以我怀疑这是一个这样的,所以我怀疑它是如何在osx上工作的,所以我是如何在osx上工作的,所以我怀疑是如何在osx上工作的,所以我怀疑是如何在osx上工作的,所以我怀疑是如何在osx上工作……<代码>代码>回波>回声>回声>回声>回声(代码>回声>回声>的工作是如何如何如何如何如何在工作的工作…………<代码>我的工作…<<<代码>回声>我的工作…<代码>回声>我是如何如何如何如何如何如何在该该该公司的工作的工作的工作的工作的工作……<<<<<<<<<代码>我问问问问问问问问问问问问问问问问问问问问问问问问问问问问问问问问问问…………<代码>我是如何如何在该-xx_-yy/zz}{}|sed's ~^[:blank:][]*\\iftoggle{[[:alnum:][u]\+}{\\ input{([[:alnum:][unum:][/]\+\}}}}{{input{\1}}.
@Sundeep我在osx上的两个建议中都得到了一个
错误:无效字符类
。请在这两个方面都尝试一个更简单的例子:
echo'{sample};sed'/{/#/'
…我没有osx,所以我不知道osx sed是否有任何特定行为…osx上的sed版本是什么?请确保,不断添加这些字符,请参见复制/粘贴
\w+
是否包含匹配的下划线?另外,如果
\input
中的路径较长,您能否提供一个示例(即包含多个
/
)@ScottWilton:参考我更新的示例&关于
\w+
的更多信息,似乎没有一个简单的解决方案可以同时匹配“input”中的较短路径和较长路径。@ScottWilton:我不确定你说的对吗?你是否在寻找一种方法,在单个捕获组中捕获
input
中的整个路径?@SLePort的答案更准确直接回答我提出的问题,但我也很欣赏perl的解决方案。你用
[:alnum:][:alnum:][:unum:][unum:][:alnum:][:unum:][unum:][unum:][unum:][unum:][unum:][/code>取代
+/code>有什么原因吗?是的,这是因为
+
不是BRE的一部分。
[:alnum unum][:alnum u][:alnum uum:][/code>相当于
(在我的问题中),ERE为我做的唯一一件事就是
+
和转义
?是的,就是这样。@SLePort:
+
获取
sed中更权威的答案
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}
sed i.bak 's~^[[:blank:]]*\\iftoggle{[[:alnum:]_][[:alnum:]_]*}{\\input{\([[:alnum:]_\/][[:alnum:]_\/]*\)}}{}~\\input{\1}~' file.txt