Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 与OR中较长字符串匹配的正则表达式 动机_Python_Regex - Fatal编程技术网

Python 与OR中较长字符串匹配的正则表达式 动机

Python 与OR中较长字符串匹配的正则表达式 动机,python,regex,Python,Regex,我正在解析地址,需要在单独的匹配中获取地址和国家,但这些国家可能有别名,例如: UK == United Kingdom, US == USA == United States, Korea == South Korea, 等等 解释 因此,我要做的是创建一个大型正则表达式,其中所有可能的国家名称(至少是那些更可能出现的国家名称)都由OR运算符分隔,如下所示: germany|us|france|chile 但问题在于多词国家名称及其较短版本,如: 摩尔多瓦共和国和摩尔多瓦 以此为例,我

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

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

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

germany|us|france|chile
但问题在于多词国家名称及其较短版本,如:

摩尔多瓦共和国
摩尔多瓦

以此为例,我们得到以下字符串:

'Somewhere in Moldova, bla bla, 12313, Republic of Moldova'
^(.*),?(?<!\w)[ ][(]?(c|o|u|n|t|r|i|e|s)[)]?(?![ ]*\w)(.*[\d\-]+.*|,.*[:/].*)?$
我想从中得到什么:

'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|...)
问题: 问题是,当有一个条目是较大条目的子集时,选择的条目越短,选择的条目越长,剩余的条目保留在基址字符串中。 有没有一种方法可以告诉正则表达式在两个值为马赫时选择最大可能的匹配

编辑
  • 我正在使用Python和内置的re模块
  • 正如m.buettner所建议的,将第一个匹配组从
    (.*)
    更改为
    (.*)
    确实解决了当前的问题,但也产生了另一个问题。考虑其他例子:

    <新加坡国立大学化学系,新加坡4512436版

  • 匹配项:

    'Department of Chemistry, National University of'
    'Singapore'
    
    现在匹配得太早了。

    您的问题是

    开头右侧的
    *
    尝试尽可能多地匹配。这就是一切,直到绳子的尽头。但是你的模式的其余部分失败了。因此,引擎回溯并丢弃与
    *
    匹配的最后一个字符,然后再次尝试模式的其余部分(仍然失败)。引擎将重复此过程(匹配失败、回溯/放弃一个字符、重试),直到它最终可以与模式的其余部分匹配。第一次出现这种情况是当
    *
    匹配到
    摩尔多瓦
    (因此
    *
    仍在消费
    共和国
    )。然后替换(仍然无法匹配
    摩尔多瓦共和国
    )将很乐意匹配
    摩尔多瓦
    ,并返回结果

    最简单的解决方案是取消重复:

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

    编辑:

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

    'Somewhere in Moldova, bla bla, 12313, Republic of Moldova'
    
    ^(.*),?(?<!\w)[ ][(]?(c|o|u|n|t|r|i|e|s)[)]?(?![ ]*\w)(.*[\d\-]+.*|,.*[:/].*)?$
    
    ^(.*),?(?
    由于lookaround实际上不是匹配的一部分,因此它们不会干扰模式的其余部分-它们只是检查匹配中特定位置的条件。我添加的两个lookaround确保:

  • 国家/地区前面的强制空格前没有单词字符
  • 国家后面没有单词字符,只有空格隔开
  • 请注意,我在字符类中包装了空格以及文字括号(而不是转义它们)。这两者都不是必需的,但我更喜欢这些可读性方面的内容,因此它们只是一个建议

    编辑2:

    正如abarnert在评论中提到的,不使用仅限正则表达式的解决方案如何


    您可以在
    上拆分字符串,然后修剪每个结果,并对照您的国家/地区列表检查这些结果(可能使用regex)。如果您的地址的任何部分与您所在的国家/地区相同,您可以返回该地址。如果存在多个1,您至少可以检测到歧义并正确处理。

    对正则表达式中的所有备选项进行排序,只需按排序(从最长到最短)以编程方式创建正则表达式即可名称数组。然后在原子组中创建整个正则表达式(PCRE引擎有它,不知道RE引擎是否也有它)。由于原子组,正则表达式引擎从不回溯到尝试原子组中的其他替代项,因此您对所有替代项进行排序,匹配项将始终是最长的


    Tada.

    如果您告诉我们您使用的是哪种语言,这会有所帮助,因为不同的语言有不同的正则表达式规则。您使用的是哪种语言/pcre库?无法复制,因为pcre在默认情况下试图贪婪。请参阅问题必须来自您的正则表达式中的某些内容,或者您将其作为非正则表达式运行greedy@Lepidosteus那是因为你没有使用他的完全正则表达式。贪婪首先是导致问题的原因,因为
    *
    将正则表达式的剩余部分推到尽可能远的地方。贪婪也不适用于交替。在您的例子中,您得到
    摩尔多瓦共和国
    的原因是,相应的匹配在目标字符串中开始得更早(从左到右尝试匹配)。与之相比,你真的需要用正则表达式解决这个问题吗?听起来你有一些含糊不清的地方(例如,
    Singapore,Singapore
    示例,从你对m.buettner的回答的评论中)你可以很容易地用祈使句来描述如何解决问题,但却不知道如何用正则表达式来描述。@alfetopito:那是我的错