【问题标题】:How to remove a possibly parenthesized expression from a string?如何从字符串中删除可能带括号的表达式?
【发布时间】:2019-04-15 16:16:49
【问题描述】:

我想使用 RegEx 从产品名称中删除版本号。名称可能如下所示:

SampleProduct 2.0

它们也可以在版本号周围有括号:

SampleProduct (2.1)

因此,我尝试为版本号定义一个组,并为带有括号的版本定义一个替代项:

\s((?<versionNumber>\d+(\.\d+)*)|\(\k<versionNumber>\))\z

但这不会产生匹配项。由于模式很小,我尝试使用索引访问组:

\s((\d+(\.\d+)*)|\(\2\))\z

这也不起作用。顺便说一句,嵌套组的索引顺序是什么?它们是按照左括号还是右括号的出现排序的?无论如何,\1\2\3 都没有匹配到。

我试图找出我是否误解了 Regex 的某个功能。当我分别尝试分组和替代方案时,它们按预期工作。但是当我混合这两个功能时,在某些时候它会停止工作,我无法发现问题。 目前我正在成功地使用没有分组的表达式来删除版本:

name = name.Substring(0, name.Length - Regex.Match(name, @"\s(\d+(\.\d+)*|\(\d+(\.\d+)*\))\z").Value.Length);

但我想避免重复模式。

【问题讨论】:

  • 在这种情况下,还有另一种解决方案 (Balanced Groups),不需要重复使用模式部分,并且可以让 OP 拥有更清晰的正则表达式。

标签: c# .net regex


【解决方案1】:

如果您想避免在正则表达式中重复模式的一部分并且只想匹配 2.0(2.0) 但不匹配 (2.02.0),您可以使用 条件 正则表达式:

(\()?\d+(?:\.\d+)*(?(1)\))

请参阅regex demo

如果只有一个括号,它将不会成为匹配的一部分。

详情

  • (\()? - 一个可选的捕获组#1:一个( char(如果没有(,则该组的值为null,后面的(?(1)...) 检查将失败)
  • \d+ - 1 位或多位数字
  • (?:\.\d+)* - 0 次或多次 . 和 1+ 位重复
  • (?(1)\)) - 条件构造:如果第 1 组匹配,则必须匹配 ),否则没有可匹配的内容(缺少 |...) 否则条件部分意味着任何东西都可以遵循之前的模式)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多