【问题标题】:Regex with negative lookahead across multiple lines多行负前瞻的正则表达式
【发布时间】:2013-09-24 11:10:14
【问题描述】:

在过去的几个小时里,我一直在尝试从以下示例数据中匹配地址,但无法正常工作:

medicalHistory      None
address             24 Lewin Street, KUBURA, 
                NSW, Australia
email               MaryBeor@spambob.com


address             16 Yarra Street, 
                                     LAWRENCE, VIC, Australia
name                Mary   Beor
medicalHistory      None
phone               00000000000000000000353336907
birthday            26-11-1972

我的计划是找到以“地址”开头的任何内容,后跟任何空格,后跟字符、数字逗号和换行符,并以换行符后跟一个字符结尾。我想出了以下(以及它的许多变体):

address\s+([0-9a-zA-Z, \n\t]+)(?!\n\w)

不幸的是符合以下条件:

address             24 Lewin Street, KUBURA,
                NSW, Australia
email               MaryBeor  

和

address             16 Yarra Street,
                                 LAWRENCE, VIC, Australia
name                Mary   Beor
medicalHistory      None
phone               00000000000000000000353336907
birthday            26

而不是

address             24 Lewin Street, KUBURA, 
                NSW, Australia

和

address             16 Yarra Street,
                                 LAWRENCE, VIC, Australia

你能告诉我我做错了什么吗?

【问题讨论】:

    标签: regex parsing lookahead


    【解决方案1】:

    我会这样做:

    address\s+((?![\r\n]+\w)[0-9a-zA-Z, \r\n\t])+
    

    看here on Regexr。

    这个((?![\r\n]+\w)[0-9a-zA-Z, \r\n\t])+ 是重要的部分,我说,匹配[0-9a-zA-Z, \r\n\t] 的下一个字符,如果(?![\r\n]+\w) 没有跟随。这符合您的预期。

    在您的两种情况下,正则表达式都停止匹配,因为您的字符类中没有包含一个字符。如果您想这样做,则需要将lazy quantifier 和positive lookahead 结合起来:

    address\s+([0-9a-zA-Z, \n\r\t]+?)(?=\r\w)
    

    [0-9a-zA-Z, \n\r\t]+? 尽可能少地匹配,直到条件 (?=\r\w) 为真。

    看here at Regexr

    【讨论】:

    • @n1te 也许是贪婪的量词+,它消耗了直到@ 之前的所有内容,并且仍然满足负前瞻。
    • @n1te 我在回答中添加了一些解释。
    • @stema 奇怪,当我通过 preg_match 运行第二个解决方案时,它似乎不起作用,但它在 Regexr 中起作用
    • @n1te,我想这是因为我只使用了\r 作为换行符,因为 regexr 有它。将\r 替换为\n 或[\r\n]+,就像我在第一个解决方案中所做的那样。
    • 两个链接都不匹配
    【解决方案2】:

    您的正则表达式的问题在于+ 是贪婪的,直到它从该组中找到一个字符,第一种情况是@,第二种情况是-。

    另一种方法是对换行符后跟单词字符使用非贪婪量词和正向预测,例如( 版本):

    re.findall(r'address\s+.*?(?=\n\w)', s, re.DOTALL)
    

    它产生:

    ['address             24 Lewin Street, KUBURA, \n                NSW, Australia',
     'address             16 Yarra Street, \n                                     LAWRENCE, VIC, Australia']
    

    【讨论】:

    • 谢谢,这是有道理的。我必须运行您的代码才能更好地理解它。感谢您的帮助
    猜你喜欢
    • 2021-10-11
    • 2011-10-14
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多