使用正则表达式分组结构匹配部分字符串

Posted

技术标签:

【中文标题】使用正则表达式分组结构匹配部分字符串【英文标题】:Matching parts of string using regex grouping constructs 【发布时间】:2019-12-25 08:16:45 【问题描述】:

我的字符串格式如下:

CC-SS[PC|PC|...|PC]

地点:

CC 是国家代码 SS 是状态码 PC|PC|...|PC 是用竖线分隔的邮政编码字符串

字符串的正确部分可能不存在。例如:

美国 美国-IL

是有效的字符串。

所以,我想使用正则表达式仅获取字符串的特定详细信息(如果存在)。

我尝试使用命名组和以下模式的一些变体:

^(?<country>.*)(?<=-)(?<state>.*)(?<=\[)(?<postalcodes>.*)(?=])

上述模式有两个问题:

首先,它仅适用于字符串的完整表示(缩短的不匹配) 其次,我无法拒绝分隔符的匹配(-[]

通常,我使用正面或负面的前瞻/后视并匹配除定界符之外的所有内容 - [^.\]],但我不确定在匹配多个组时如何应用此技术。

任何人都可以建议我可以尝试的东西吗?

【问题讨论】:

我个人认为,虽然功能强大,但正则表达式并不总是最好的选择,因为它会导致难以阅读和调试代码。使用自定义函数解析上述字符串会相当简单。 @TimRutter 谢谢。我现在就是这样做的。只是想知道我是否可以使用正则表达式使其更短/更智能。 一般建议:不要使用.* 和前瞻,使用负字符类将字符匹配到分隔符。例如,要匹配直到第一个 - 的所有内容,只需匹配 [^-]+ \b(?&lt;country&gt;[A-Z]2)(?:-(?&lt;state&gt;[A-Z]2))?\b(?:\[(?&lt;postalcodes&gt;[^][]*]))??见this demo @WiktorStribiżew 它似乎有效。我现在将进行更多测试。 【参考方案1】:

我觉得你可以用

\b(?<country>[A-Z]2)(?:-(?<state>[A-Z]2))?\b(?:\[(?<postalcodes>[^][]*)])?

在 C# 中:

var rx = new Regex(@"\b(?<country>[A-Z]2)(?:-(?<state>[A-Z]2))?\b(?:\[(?<postalcodes>[^][]*)])?");

请参阅regex demo。

详情

\b - 单词边界 (?&lt;country&gt;[A-Z]2) - 组“国家”:两个大写 ASCII 字母 (?:-(?&lt;state&gt;[A-Z]2))? - 一个可选的非捕获组,匹配 1 次或 0 次出现 - - 一个连字符 (?&lt;state&gt;[A-Z]2) - 组“状态”:两个大写 ASCII 字母 \b - 单词边界 (?:\[(?&lt;postalcodes&gt;[^][]*)])? - 一个可选的非捕获组,匹配 1 次或 0 次 \[(?&lt;postalcodes&gt;[^][]*) - 组“邮政编码”:除 ][ 之外的 0 个或多个字符 ] - ] 字符。

【讨论】:

谢谢。我不知道我可以使用?: 结合capturing 子组。 @gotqn 组甚至环视可以嵌套。

以上是关于使用正则表达式分组结构匹配部分字符串的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式中分组功能高级用法

Python 正则表达式 利用括号分组

正则表达式分组与 C++ 11 正则表达式库匹配

正则表达式匹配逗号不在分组符号之间

Python爬虫编程思想(32):正则表达式的分组

JS正则表达式从入门到入土—— 分组