gpt4 book ai didi

python - 匹配 OR 中较长字符串的正则表达式

转载 作者:太空狗 更新时间:2023-10-29 18:32:55 24 4
gpt4 key购买 nike

动机

我正在解析地址,需要在单独的匹配项中获取地址和国家/地区,但这些国家/地区可能有别名,例如:

UK == United Kingdom, 
US == USA == United States,
Korea == South Korea,

等等……

说明

因此,我所做的是创建一个大的正则表达式,其中包含所有可能的国家/地区名称(至少是那些更有可能出现的国家/地区名称),由 OR 运算符分隔,如下所示:

germany|us|france|chile

但问题在于多词国家名称及其较短的版本,例如:

摩尔多瓦共和国摩尔多瓦

以此为例,我们有字符串:

'Somewhere in Moldova, bla bla, 12313, Republic of Moldova'

我想从中得到什么:

'Somewhere in Moldova, bla bla, more bla, 12313'
'Republic of Moldova'

但这就是我得到的:

'Somewhere in Moldova, bla bla, 12313, Republic of'
'Moldova'

正则表达式

由于有几种情况,这里是我目前使用的:

^(.*),? \(?(republic of moldova|moldova)\)?(.*[\d\-]+.*|,.*[:/].*)?$

因为我们可能在国家名称后有传真、电话、邮政编码或其他内容——我不关心这些——我使用最后一个匹配组来删除它们:

(.*[\d\-]+.*|,.*[:/].*)?

此外,有时国家名称会括在括号中,所以我在第二个匹配组周围有 \(?\)?,所有国家都在里面它:

(republic of moldova|moldova|...)

问题

事情是,当有一个条目是一个更大的条目的子集时,选择较短的条目而不是较长的条目,其余部分保留在 base_address 字符串中。当两个值匹配时,有没有办法告诉正则表达式选择最大可能的匹配项?

编辑

  1. 我正在使用内置 re 模块的 Python
  2. 根据 m.buettner 的建议,将第一个匹配组从 (.*) 更改为 (.*?) 确实解决了当前问题,但是它还创建了另一个。考虑其他示例:

    '新加坡国立大学化学系, 4512436 Singapore'

匹配:

'Department of Chemistry, National University of'
'Singapore'

这里它现在匹配得太快了。

最佳答案

你的问题是greediness .

开头的 .* 尝试尽可能匹配。这就是字符串末尾之前的所有内容。但是你的模式的其余部分失败了。因此引擎回溯并丢弃与 .* 匹配的最后一个字符并再次尝试模式的其余部分(仍然失败)。引擎将重复这个过程(匹配失败,回溯/丢弃一个字符,再试一次)直到它最终可以与模式的其余部分匹配。第一次发生这种情况是 .* 匹配到 Moldova 的所有内容(因此 .* 仍在消耗 Republic of).然后交替(仍然无法匹配 摩尔多瓦共和国)将很乐意匹配 moldova 并将其作为结果返回。

最简单的解决方案是让重复变得不贪婪:

^(.*?)...

请注意,量词后面的问号并不表示“可选”,而是表示“不可取”。这只是简单地颠倒了行为:引擎首先尝试完全省略 .*,并且在回溯过程中,它在每次尝试匹配模式的其余部分失败后又包含一个字符。

编辑:

通常有更好的选择来替代不贪婪。正如您在评论中所述,不理想的解决方案带来了另一个问题,即字符串较早部分的国家/地区可能会匹配。你可以做的是使用 lookarounds确保在国家/地区之前或之后没有单词字符(字母、数字、下划线)。这意味着,只有在国家/地区单词被逗号或字符串的任一端包围时才会匹配:

^(.*),?(?<!\w)[ ][(]?(c|o|u|n|t|r|i|e|s)[)]?(?![ ]*\w)(.*[\d\-]+.*|,.*[:/].*)?$

由于 lookarounds 实际上并不是匹配的一部分,它们不会干扰您模式的其余部分 - 它们只是检查匹配中特定位置的条件。我添加的两个环视确保:

  1. 国家前面的必填空格前没有单词字符。
  2. 国家之后没有单词字符,仅由空格分隔。

请注意,我在字符类中包装了空格,以及文字括号(而不是转义它们)。两者都不是必需的,但我更喜欢这些可读性,所以它们只是一个建议。

编辑 2:

正如 abarnert 在评论中提到的那样,不使用仅使用正则表达式的解决方案怎么样?

您可以在 , 上拆分字符串,然后修剪每个结果,并根据您的国家/地区列表检查这些结果(可能使用正则表达式)。如果您地址的任何组成部分与您所在的国家/地区相同,您可以将其退回。如果有多个,至少你可以检测到歧义并正确处理它。

关于python - 匹配 OR 中较长字符串的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16619401/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com