Python图案消极向后看



我试图找出一个匹配文件路径字符串的regex模式,其中一个名为"cmd.exe"的文件不位于"System32"文件夹或它的任何子文件夹中。

Pattern应该匹配:

C:Toolscalc.exe

但不在此:

C:WindowsSystem32calc.exe
C:WindowsSystem32De-decalc.exe

我试着消极地看后面:

(?<![Ss]ystem32)\calc.exe
(?<![Ss]ystem32).*\calc.exe
(?<![Ss]ystem32[.*])\calc.exe

但是到目前为止都没有效果。有人看到我的错误了吗?

你可以看到我的例子,并尝试自己在这里:http://rubular.com/r/syAoEn7xxx

谢谢你的帮助。

要回答这个问题的正则表达式方面,问题是re不支持可变长度的回溯:

rx = r'(?<!System32.*)calc.exe'
re.search(rx, r'C:Toolscalc.exe')
> sre_constants.error: look-behind requires fixed-width pattern

有两种解决方法:

安装并使用更新的regex模块,它支持这个功能(以及更多):

rx = r'(?<!System32.*)calc.exe'
print regex.search(rx, r'C:Toolscalc.exe')  # <_regex.Match object at 0x1028dd238>
print regex.search(rx, r'C:WindowsSystem32calc.exe') # None

或重新表达表达式,使其不需要变量后看:

rx = r'^(?!.*System32).*calc.exe'
print re.search(rx, r'C:Toolscalc.exe')  # <_sre.SRE_Match object at 0x10aede238>
print re.search(rx, r'C:WindowsSystem32calc.exe') # None

在处理文件名时应该使用os.path -module中的函数。

我提出:

from os.path import basename, dirname
paths = [r"C:Toolscalc.exe",
         r"C:WindowsSystem32calc.exe",
         r"C:WindowsSystem32De-decalc.exe"]
good_paths = [p for p in paths if basename(p).lower() == "calc.exe"
                               and not "system32" in dirname(p).lower()]

核心是paths的列表推导,检查basename(路径的最后一部分)和dirname(包含目录的名称)。

不使用regex也可以。

def iter_good_paths(list_of_paths):
    for path in list_of_paths:
        parts = path.lower().split(r'')
        if parts[-1] == 'calc.exe' and 'System32' in parts:
            yield path

,像这样使用

print list(iter_good_paths(list_of_paths)) 

这里不需要向后看,更不用说可变宽度了。请使用提前查找:

(?i)^(?:(?!\System32\).)*\calc.exe$

这将匹配在所需的calc.exe字符串之前不包含大小写不敏感字符串system32的任何内容。表达式的(?i)部分使得它右边的所有内容不区分大小写(如果这是一个windows文件系统,这可能是一个很好的选择)。

我很乐意推荐正则表达式。info。它是学习正则表达式的许多特性和风格的优秀资源。

最新更新