代码之家  ›  专栏  ›  技术社区  ›  Allen Qin

Python Regex:匹配不在单词前面或后面有数字的字符串

  •  0
  • Allen Qin  · 技术社区  · 6 年前

    我想在Python中有一个Regex来替换一个不带数字的单词前面或后面的字符串。

    对于下面的句子,

    四月

    今天是四月四日。她的名字是 . 明天是四月五日。

    我试着用这个正则表达式:

    (\w*(?<!\w*\d\w*\s)April(?!\s\w*\d\w*))
    

    但是,我有个错误说:

    error: look-behind requires fixed-width pattern
    

    0 回复  |  直到 6 年前
        1
  •  2
  •   Cary Swoveland    6 年前

    这是一个可以使用的正则表达式:

    (?:^\s+|[^\w\s]+\s*|\b[^\d\s]+\s+)(April)\b(?!\s*\w*\d)
    

    设置了case-independent标志。在捕获组1中捕获目标单词。

    Demo

    Python的regex引擎执行以下操作:

    (?:           # begin non-cap grp
      ^           # match beginning of line
      \s*         # match 0+ whitespace characters
      |           # or
      [^\w\s]+    # match 1+ chars other than word chars and whitespace
      \s*         # match 0+ whitespace chars
      |           # or
      \b          # match word break
      [^\d\s]+    # match 1+ chars other than digits and whitespace
      \s+         # match 1+ whitespace chars
    )             # end non-cap grp  
    (April)       # match 'April' in capture group
    \b            # match word break
    (?!           # begin negative lookahead
      \s*         # match 0+ whitespace chars         
      \w*         # match 0+ word chars
      \d          # match a digit
    )             # end negative lookahead
    

    我所采取的方法是指明可能发生的事 "April" 为什么不跟着它走呢。我不能说明什么不能先于 “四月” 因为这需要一个否定的lookbehind,这是Python的regex引擎不支持的。

    我认为

    • 在字符串的开头,后面可能有空格;
    • 前接不含数字的单词,后面可能有空格。

    我也这么认为 后跟一个分词符,该分词不能后跟包含数字的单词,前面可能有空格。

        2
  •  1
  •   Toto    6 年前

    这是可以做到的 Pypi regex library 它支持可变长度的lookbehind。

    import regex
    
    str = 'Today is 4th April. Her name is April. Tomorrow is April 5th.'
    res = regex.sub(r'(?<!\d[a-z]* )April(?! [a-z]*\d)', 'PERSON', str)
    print(res)
    

    输出:

    Today is 4th April. Her name is PERSON. Tomorrow is April 5th.
    

    说明:

    (?<!\d[a-z]* )      # negative lookbehind, make sure we haven't a digit followed by 0 or more letters and a space before
    April               # literally
    (?! [a-z]*\d)       # negative lookahead, make sure we haven't a space, 0 or more letters and a digit after
    

    更新 re

    import re
    
    str = 'Today is 4th April. Her name is April. Tomorrow is April 5th.'
    res = re.sub(r'(\b[a-z]+ )April(?! [a-z]*\d)', '\g<1>PERSON', str)
    print(res)