如何在正则表达式中反向引用“内部”选择( () )?

Posted

技术标签:

【中文标题】如何在正则表达式中反向引用“内部”选择( () )?【英文标题】: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 说这个匹配是可选的。 。匹配单个字符。 \。在这种情况下匹配句点或小数。

【问题讨论】:

【参考方案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 字符是安全的:它不会造成任何伤害。 [+][\+] 这两个类都将匹配文字 +。恕我直言,第一个是首选,因为我发现一个正则表达式有太多难以阅读的转义。但有些人会不同意我的观点,并发现通过使用转义符(虽然不是必需的)更清楚的是,匹配的是文字 + 而不是贪婪的量词。

希望能解决问题。

【讨论】:

此答案已添加到 Stack Overflow Regular Expression FAQ 的“字符类”下。【参考方案3】:

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

【讨论】:

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

以上是关于如何在正则表达式中反向引用“内部”选择( () )?的主要内容,如果未能解决你的问题,请参考以下文章

在 sed 中使用反向引用正则表达式

正则表达式;反向引用字符集中不匹配的字符

Java中的正则表达式反向引用

PHP正则表达式 - 替换一个反向引用[重复]

是否有用于反向引用的大写/小写版本的正则表达式替换术语? [复制]

正则表达式反向引用乘法[重复]