替换正则表达式意外结果

替换正则表达式意外结果

我正在尝试更换关键词{}{date}或 之类的大括号标记。为此,我使用正则表达式。{name}%@{(.*?)\}

所以,我写了这个测试脚本:

echo "hello { welcome } and { welcome} home {friend } {(friend)}" | sed "s; {\(.*\?\)\}; %@; g"

output: hello %@

但我期待hello %@ and %@ home %@ %@结果。

更简单的替换工作完美:

echo "hello {} and {} home {} {}" | sed -e "s; {\}; %@; g"

output: hello %@ and %@ home %@ %@

现在我被困在如何解决这个问题的 0 个想法中。

答案1

 {\(.*\?\)\}

看,这.*是贪婪的,因此上述正则表达式将从第一行{到最后}一行进行匹配。这证明了输出的合理性。

另请注意,您没有对捕获组执行任何操作\( \),因此可以将它们删除,并且不需要转义最后一个大括号。所以正则表达式可以重写为{.*\?}.

也许您的困惑是因为您习惯了 Perl 正则表达式?在Perl regex中,.*?是非贪婪的,但sed不使用它们,它使用BRE基本正则表达式。

现在,要获得所需的输出,请执行

 {[^}]*}

这将匹配大括号内的每个值,表示[^}]*“任意数量的非}字符”。

$ echo "hello { welcome } and { welcome} home {friend } {(friend)}" | 
  sed "s; {[^}]*}; %@; g"
hello %@ and %@ home %@ %@

相关内容