如何编写SED正则表达式以提取由另一个字符串分隔的字符串?

时间:2013-03-05 12:10:18

标签: regex sed

我正在使用GNU sed版本4.2.1,我正在尝试编写一个非贪婪的SED正则表达式来提取由另外两个字符串分隔的字符串。当分隔字符串是单字符时,这很容易:

s:{\([^}]*\)}:\1:g

在该示例中,字符串由' {'在左边和'}'在右边。

如果分隔字符串是多个字符,请说' {{{'和'}}}'我可以像这样调整上面的表达式:

s:{{{\([^}}}]*\)}}}:\1:g

所以中心表达式匹配任何不包含'}}}'关闭字符串。但这只适用于匹配字符串不包含'}'一点都不类似的东西:

{{{cannot match {this broken} example}}}

无效,但

{{{can match this example}}}

确实有效。当然

s:{{{\(.*\)}}}:\1:g

总是有效,但是贪婪,所以不适合在同一条线上出现多个模式的地方。

我理解[^a]除了a[^ab]之外的其他任何内容都意味着除了ab以外的任何内容,所以,尽管它似乎有用,但我不知道#39; t认为[^}}}]是排除3个连续字符序列的正确方法。

那么如何为SED编写一个匹配字符串的正则表达式,该字符串与另外两个字符串分隔?

2 个答案:

答案 0 :(得分:1)

[^}}}]不起作用是对的。否定的字符类匹配任何不是其中一个字符的内容。重复字符不会改变逻辑。所以你写的和[^}]一样。 (当表达式中没有大括号时,很容易理解为什么会这样有效。)

在Perl和兼容的正则表达式中,您可以使用?制作*+非贪婪:

 s:{{{(.*?)}}}:$1:g

这将始终与开场}}}后的第一个{{{匹配。

然而,this is not possible in Sed。事实上,我认为Sed没有办法做这场比赛。唯一的另一种方法是使用先行的高级功能,Sed也没有。

您可以使用-pe选项以类似sed的方式轻松使用Perl,这会导致它从命令行(-e)获取一行代码并自动遍历每一行并打印结果(-p)。

perl -pe 's:{{{(.*?)}}}:$1:g'

用于就地编辑文件的-i选项也很有用,但请确保您的正则表达式是正确的!

有关详细信息,请参阅perlrun

答案 1 :(得分:0)

使用sed,您可以执行以下操作:

sed -e :a -e 's/\(.*\){{{\(.*\)}}}/\1\2/ ; ta'

使用:

{{{can match this example}}} {{{can match this 2nd example}}}

这给出了:

can match this example can match this 2nd example

这不是懒惰的匹配,但是从右到左替换我们可以利用sed的贪婪。