【问题标题】:How to back reference "inner" selections ( () ) in a regular expression?如何在正则表达式中反向引用“内部”选择( () )?
【发布时间】:2022-01-14 16:58:15
【问题描述】:

如何在 Regex 中反向引用内括号?

示例数据是一个产品价格表,根据购买的数量显示不同的价格区间。格式为 quantityLow - quantityHigh : pricePer ;倍数。

我使用 LINQPad 构造了这个 C# Regex 表达式来分隔各个部分,它显示了 Regex 数据分离的便捷可视化。在此示例中,存在“内部”括号(选择),创建了分层数据结构。

string mys = "1-4:2;5-9:1.89";
Regex.Matches (mys, @"((\d+)[-|\+](\d*):(\d+\.?\d*);?)").Dump();  // Graphically show

这分解为(比赛就是一切。在比赛中,有单场比赛和小组赛。在小组赛中是一些单场比赛。)

  • MatchCollection(2 项)
    • 组集合(4 项)
      • CaptureCollection(1 项)() 组“1-4:2;”
      • CaptureCollection(1 项)()组“1”
      • CaptureCollection(1 项)()组“4”
      • CaptureCollection(1 项)()组“2”
    • CaptureCollection(1 项)() 匹配“1-4;2;”
    • 组集合(4 项)
      • CaptureCollection(1 项)()组“5-9:1.89”
      • CaptureCollection(1 项)()组“5”
      • CaptureCollection(1 项)()组“9”
      • CaptureCollection(1 项)()组“1.89”
    • CaptureCollection(1 项)()匹配“5-9:1.89”

仅供参考:

  • () 括号组找到了可以被 \1..\9 引用的结果(我认为)。
  • \d 匹配单个数字。后面的 + 匹配一位或多位数字。 * 在匹配零个或多个数字之后。 ? after 说这个匹配是可选的。
  • 。匹配单个字符。 \。在这种情况下匹配句点或小数。

【问题讨论】:

    标签: regex


    【解决方案1】:

    像往常一样使用\1 ... \9(或$1 ... $9 在某些正则表达式实现中)。编号是从左到右的,基于开放括号的位置(因此嵌套组的编号高于其嵌套的组)。

    【讨论】:

    • \k<foo> 反向引用命名组(?<foo>...),当有太多时。
    • 有人有任何示例代码来使用自动编号(身份)进行命名反向引用吗?像 (?[1-8]...) 之类的东西,其中包含 name1、name2、name3、name4 等...?
    【解决方案2】:

    请注意,这是对 Zim 博士评论的回复:

    “奇怪的是,这两种方式似乎都可以正常工作。我选择了“调节器”,它至少显示了正则表达式是如何分解的。如果它具有设置实现的功能,我想我在做生意。”

    但是我的回答对于评论框来说太长了。

    不,您不需要转义加号,在这种情况下是连字符。在字符类中,以下字符具有特殊含义:]^-。这三个字符是唯一可能需要转义的字符(注意[ 不需要转义!)。我说 可能 因为这取决于这些元字符出现的位置。 ^ 仅在放置在字符类的开头时才具有特殊含义(作为否定指示符),在其他地方,它不需要转义,只会匹配文字 ^。一些例子来说明:

    [^a]   // special meaning: matches any character except 'a'
    [a^]   // matches 'a' or '^'
    [\^a]  // matches '^' or 'a'
    

    连字符只有在放在字符类的开头或结尾时才具有特殊含义(作为范围指示符)。例子:

    [a-c]  // special meaning: matches 'a', 'b' or 'c'
    [ac-]  // matches 'a', 'c' or '-'
    [-ac]  // matches '-', 'a' or 'c'
    [a\-c] // matches 'a', '-' or 'c'
    

    毫无疑问,一些正则表达式的实现可能与我刚刚发布的有所不同,但大多数语言都将遵守这些规则(至少我使用过的所有语言!)。正如您所注意到的,在字符类中 over escape 字符是安全的:它不会造成任何伤害。 [+][\+] 这两个类都将匹配文字 +。恕我直言,第一个是首选,因为我发现一个正则表达式有太多难以阅读的转义。但有些人会不同意我的观点,并发现通过使用转义符(虽然不是必需的)更清楚的是,匹配的是文字 + 而不是贪婪的量词。

    希望能解决问题。

    【讨论】:

    【解决方案3】:

    作为旁注,字符类总是匹配单个字符,“普通”元字符不适用于它们。所以你的类[-|\+] 匹配三个字符-|+ 之一。如您所见,逻辑 OR 元字符在字符类中没有特殊含义。而且您不需要在字符类中转义 + 字符,所以应该这样做:[-+]

    【讨论】:

    • 经过研究,我同意管道不是“或”,但您是否仍需要在类括号内“引用”减号和加号?例如:/^[\d\s()\-\+\/]*$/ 将匹配电话号码 714/921-5424(来自 VisiBone 图表的示例),或者此实现依赖于?
    • 奇怪的是,这两种方式似乎都可以正常工作。我选择了“Regulator”,它至少显示了正则表达式是如何分解的。如果它有设置实现的功能,我想我在做生意。
    • 注意/^[\d\s\(\)\-\+\/]*$/类等价于/^[\d\s()+\/-]*$/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多