【问题标题】:Replace string with matched expression用匹配的表达式替换字符串
【发布时间】:2019-03-16 21:51:29
【问题描述】:

我在多个文件Hello{Some Text}中有以下文本,我想用Some Text替换它。其中Some Text 可能包括平衡括号{ }。例如:Hello{Some { other} Text} 应替换为 Some { other} Text

sedawkperl 或其他工具中是否有简单的方法来实现这一点?

【问题讨论】:

  • 你必须选择perl。尝试Hello({((?:[^{}]*+|(?1))*)}) 并替换为\2。在此处查看现场演示regex101.com/r/AIlUV5/1
  • Regex 在直接找到平衡的分隔符方面是出了名的糟糕,而没有一个非常复杂的表达式。一些替代方案是 Text::Balanced 或使用 Parser::MGC 之类的东西标记您的文本。

标签: regex perl awk sed


【解决方案1】:

你必须选择perl,因为它支持子程序调用。 {[^{}]*} 上的递归匹配应该连续发生,如果找到不平衡的大括号,则应该失败。下面的正则表达式完成了这项工作:

Hello({((?:[^{}]*+|(?1))*)})

live demo here

注意:面对转义大括号时会失败。

Perl:

$ echo 'Hello{Some { other} Text}' | perl -pe 's~Hello({((?:[^{}]*+|(?1))*)})~$2~g'
Some { other} Text

正则表达式分解:

Hello # Match `Hello`
( # Start of 1st capturing group
    { # Match `{`
    ( # Start of 2nd capturing group
        (?: # Start of non-capturing group
            [^{}]*+ # Match anything but `{` or `}` possessively
            | # Or
            (?1) # Recurs first group
        )* # End of NCG, repeat as much as possible
    ) # End of 2nd CP
    } # Match `}`
) # End of 1st CP

【讨论】:

  • 这里真的需要所有格量词吗(在交替的左侧)?如果没有,它也能很好地工作,也许兴趣在其他地方,可能需要某种优化?
  • @PJProudhon 需要避免灾难性的故障回溯。看看没有它会发生什么regex101.com/r/AIlUV5/2
  • 谢谢!您能否解释一下“面对转义大括号时失败”是什么意思?
  • @Tohiko 当然。这意味着Hello{Some{ \{Text}} 不会产生匹配。此正则表达式与转义大括号不匹配。
猜你喜欢
  • 2015-11-30
  • 2013-10-24
  • 2012-01-25
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多