我想找到一种更好的方法来获得结果。我使用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
答案 0 :(得分:1)
您可能会使用一种黑客手段,即在预期匹配之前捕获php
或python
,如果该组不为空(如果已匹配),则丢弃当前匹配,否则丢弃该匹配有效。
请参见
pattern = re.compile(r"(?:(php|python).*?)?((?:\d+\s?[^\W\d_]+\s?)?\d{2}\s?\d{3}\s?\w.+)")
模式包含2个捕获组:
(?:(php|python).*?)?
-最后一个?
使该组成为可选,它匹配并捕获到组1 php
或python
中,然后捕获到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