【问题标题】: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 quantifierpositive 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
    相关资源
    最近更新 更多