代码之家  ›  专栏  ›  技术社区  ›  J. Doe

Python正则表达式无固定宽度的负lookback匹配

  •  1
  • J. Doe  · 技术社区  · 6 年前

    我想找到一个更好的方法来得到我的结果。我用一个 regex pattern (DD+ some text DDDD some other text) 当且仅当它不在非固定宽度查找项的前面时。我怎样才能把这些术语包含在我的语言中 REGEX pattern

    aa = pd.DataFrame({"test": ["45 python 00222 sometext",
                                "python white 45 regex 00 222 somewhere",
                                "php noise 45 python 65000 sm",
                                "otherword 45 python 50000 sm"]})
    pattern = re.compile("(((\d+)\s?([^\W\d_]+)\s?)?(\d{2}\s?\d{3})\s?(\w.+))")
    aa["result"] = aa["test"].apply(lambda x: pattern.search(x)[0] if pattern.search(x) else None)
    lookbehind = ['python', 'php']
    aa.apply(lambda x: "" if any(look in x["test"].replace(x["result"], "") for look in lookbehind) else x["result"], axis=1)
    

    输出是我所期望的

    0    45 python 00222 sometext
    1                            
    2                            
    3          45 python 50000 sm
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Wiktor Stribiżew    6 年前

    php python 在预期匹配之前,如果组不为空(如果匹配),则放弃当前匹配,否则匹配有效。

    看到了吗

    pattern = re.compile(r"(?:(php|python).*?)?((?:\d+\s?[^\W\d_]+\s?)?\d{2}\s?\d{3}\s?\w.+)")
    

    • (?:(php|python).*?)? -最后一个 ? 菲律宾比索 ,然后是0+个字符,尽可能少
    • ((?:\d+\s?[^\W\d_]+\s?)?\d{2}\s?\d{3}\s?\w.+) -这是第二组,基本上是你的模式,没有多余的组。

    如果组1匹配,我们需要返回一个空结果,否则,组2值:

    def callback(v):
        m = pattern.search(v)
        if m and not m.group(1):
            return m.group(2)
        return ""
    
    aa["test"].apply(lambda x: callback(x))
    

    0    45 python 00222 sometext
    1                            
    2                            
    3          45 python 50000 sm
    
        2
  •  1
  •   Valdi_Bo    6 年前

    作为消极的回头看必须是 固定长度 ,你必须使用 ,锚定到字符串的开头,检查

    它应包括:

    • 非数字序列(可能为空)。
    • 你的任何一根“禁”弦。

    这样,如果要检查的字符串包含 菲律宾比索 之前 第一个数字,这个lookahead将失败,阻止这个字符串 进一步处理。

    因为 ^ 非数字(在“DD+”部分之前是什么),然后应该有您的 正则表达式。

    因此要使用的正则表达式如下:

    ^(?!\D*(?:python|php))\D*(\d+)\s?([^\W\d_]+)\s?(\d{2}\s?\d{3})\s?(\w+)
    

    细节:

    • ^(?! -字符串开头和负展望:
      • \D* -非数字序列(可以是空的)。
      • (?:python|php) -一种“禁止”的字符串,作为非捕获字符串 组(无需捕获)。
    • ) -负面展望结束。
    • \D级*
    • (\d+)\s? -第一个数字序列+可选空格。
    • ([^\W\d_]+)\s? -一些文本1+可选空格。
    • (\d{2}\s?\d{3})\s? -第二个数字序列(可选
    • (\w+) -一些2号文本。

    我的解决方案比其他解决方案的优点是你不受 检查第一组是否匹配。在这里你只得到“积极的” 不需要任何检查的箱子。

    https://regex101.com/r/gl9nWx/1