如何在正则表达式中反向引用“内部”选择( () )?
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>...)
,当有太多时。
有人有任何示例代码来使用自动编号(身份)进行命名反向引用吗?像 (?请注意,这是对 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()+\/-]*$/
以上是关于如何在正则表达式中反向引用“内部”选择( () )?的主要内容,如果未能解决你的问题,请参考以下文章