没有固定宽度的Python Regex负向后匹配

时间:2018-10-09 15:35:02

标签: python regex

我想找到一种更好的方法来获得结果。我使用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 个答案:

答案 0 :(得分:1)

您可能会使用一种黑客手段,即在预期匹配之前捕获phppython,如果该组不为空(如果已匹配),则丢弃当前匹配,否则丢弃该匹配有效。

请参见

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

模式包含2个捕获组:

  • (?:(php|python).*?)?-最后一个?使该组成为可选,它匹配并捕获到组1 phppython中,然后捕获到0+个字符,并尽可能少
  • ((?:\d+\s?[^\W\d_]+\s?)?\d{2}\s?\d{3}\s?\w.+)-这是第2组,基本上是您的模式,没有冗余组。

如果第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

答案 1 :(得分:1)

由于后面的负向观察必须为固定长度,因此您必须使用 超前超前,定位到字符串的开头,检查 第一位数字之前的部分。

其中应包括:

  • 一系列非数字(可能为空)。
  • 您的“禁止”字符串中的任何一个。

这样,如果要检查的字符串包含 python php 之前 第一个数字,该超前将失败,从而阻止了该字符串 进一步处理。

由于^锚,其余正则表达式必须首先与序列匹配 非数字(“ 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

相关问题