如果密钥不存在,正则表达式匹配文件路径的一部分

时间:2012-10-18 16:10:49

标签: python regex

如果在python中使用正则表达式不包含某个关键字,我试图匹配文件路径的一部分。例如,将正则表达式应用于“/ exclude / this / test / other”不应该匹配,而“/ this / test / other”应该返回不包括“other”的文件路径,即“/ this / test”,以及其他“其他”是任何目录。到目前为止我正在使用这个

In [153]: re.findall("^(((?!exclude).)*(?=test).*)?", "/exclude/this/test/other")
Out[153]: [('', '')]

re.findall("^(((?!exclude).)*(?=test).*)?", "/this/test/other")
Out[152]: [('/this/test/other', '/')]

但我不能让它在“测试”之后停止匹配,也有一些空的匹配。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

如果您只需要检查关键字是否存在,只需使用in

In [33]: s1="/exclude/this/test"

In [34]: s2="this/test"

In [35]: 'exclude' in s1
Out[35]: True

In [36]: 'exclude' in s2
Out[36]: False

编辑: 或者如果你想要路径直到测试:

if 'exclude' not in s:
    re.findall(r'(.+test)',s)

答案 1 :(得分:2)

您获得了额外的结果,因为(1)您使用findall()代替search(),以及(2)您正在使用捕获组而不是非捕获

>>> import re
>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/test").group(0)
'/this/test'

这也适用于findall(),但是当你匹配整个字符串时,这没有用。更重要的是, include 部分正则表达式不起作用。检查一下:

>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/foo").group(0)
'/this/foo'

这是因为*中的(?=test)*使前瞻可选,这使得它毫无意义。但摆脱*并不是一个真正的解决方案,因为excludetest可能是较长字词的一部分,例如excludexxyyytest。这是一个更好的正则表达式:

r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$'

测试:

>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/test').group()
'/this/test'
>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/foo').group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

编辑:我看到您修复了“可选前瞻”问题,但现在整个正则表达式都是可选的!

编辑:如果您希望在/test之后停止匹配,请尝试以下操作:

r'^(?:/(?!test\b|exclude\b)\w+)*/test\b'

(?:/(?!test\b|exclude\b)\w+)*匹配零个或多个路径组件,只要它们不是/test/exclude

答案 2 :(得分:1)

如果您的匹配比使用in和简单关键字更复杂,那么您可能会更清楚地了解两个正则表达式:

import re
s1="/exclude/this/test"
s2="this/test"

for s in (s1,s2):
    if re.search(r'exclude',s): 
        print 'excluding:',s
        continue
    print s, re.findall(r'test',s)

打印:

excluding: /exclude/this/test
this/test ['test']

如果这是您的目标,您可以将两个正则表达式压缩:

print [(s,re.findall(r'test',s)) for s in s1,s2 if not re.search(r'exclude',s)]

修改

如果我理解你的编辑,这可行:

s1="/exclude/this/test/other"
s2="/this/test/other"

print [(s,re.search(r'(.*?)/[^/]+$',s).group(1)) for s in s1,s2 if not re.search(r'exclude',s)]

打印:

[('/this/test/other', '/this/test')]