负向前瞻断言不在python中工作

时间:2012-12-14 02:32:06

标签: python regex assertion lookahead

任务:
- 给定:图像列表文件名
- todo:创建一个文件名不包含单词“thumb”的新列表 - 即仅定位非缩略图图像(使用PIL - Python Imaging Library)。

我已经尝试r".*(?!thumb).*",但失败了。

我找到了解决方案(此处在stackoverflow上),将^添加到正则表达式,并将.*置于否定前瞻:r"^(?!.*thumb).*",现在可以正常工作。< / p>

问题是,我想了解为什么我的第一个解决方案不起作用,但我不这样做。 由于正则表达式足够复杂,我真的很想理解它们。

我理解的是^告诉解析器在字符串的开头要满足以下条件。但是,(不工作)第一个例子中的.*也不是从字符串的开头开始的吗? 我认为它会从字符串的开头开始,并在到达“拇指”之前搜索尽可能多的字符。如果是这样,它将返回不匹配。

有人可以解释为什么r".*(?!thumb).*"不起作用,r"^(?!.*thumb).*"却有效吗?

谢谢!

3 个答案:

答案 0 :(得分:5)

  

有人可以解释为什么r".*(?!thumb).*"不起作用   r"^(?!.*thumb).*"呢?

第一个将始终匹配,因为.*将消耗所有字符串(因此不能为负向前瞻失败的任何事物后跟)。第二个是有点复杂的,并且将从行的开头匹配,最多的字符直到它遇到“拇指”并且如果存在,那么整个匹配失败,因为该行开始后面跟着'拇指'

第二个更容易写成:

  • 'thumb' not in string
  • not re.search('thumb', string)(而不是匹配)

正如我在评论中提到的,你的问题是:

  

文件名不包含 “拇指”

因此,您可能希望考虑是否应该排除thumbs up

答案 1 :(得分:2)

(Darn,Jon打败了我。好吧,你可以看看这些例子)

就像其他人说的那样,正则表达式并不是这项工作的最佳工具。如果您正在使用文件路径,请查看os.path

对于您不想要的过滤文件,一旦解剖了路径(if 'thumb' not in filename: ...filename),您就可以str

对于后代,这是我对那些正则表达式的看法。 r".*(?!thumb).*"不起作用,因为.*是贪婪的,前瞻的优先级非常低。看看这个:

>>> re.search('(.*)((?!thumb))(.*)', '/tmp/somewhere/thumb').groups()
('/tmp/somewhere/thumb', '', '')
>>> re.search('(.*?)((?!thumb))(.*)', '/tmp/somewhere/thumb').groups()
('', '', '/tmp/somewhere/thumb')
>>> re.search('(.*?)((?!thumb))(.*?)', '/tmp/somewhere/thumb').groups()
('', '', '')

最后一个很奇怪......

另一个正则表达式(r"^(?!.*thumb).*")有效,因为.*位于前瞻内部,因此您不会遇到任何字符被盗的问题。您实际上甚至不需要^,具体取决于您使用的是re.match还是re.search

>>> re.search('((?!.*thumb))(.*)', '/tmp/somewhere/thumb').groups()
('', 'humb')
>>> re.search('^((?!.*thumb))(.*)', '/tmp/somewhere/thumb').groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
>>> re.match('((?!.*thumb))(.*)', '/tmp/somewhere/thumb').groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'

答案 2 :(得分:0)

忽略关于正则表达式的所有内容,您的任务似乎相对简单:

  
      
  • 给出:图像文件名列表
  •   
  • todo:创建一个新的列表,其文件名不包含单词“thumb” - 即仅定位非缩略图图像(使用PIL - Python   影像库)。
  •   

假设您有一个类似于以下内容的文件名列表:

filenames = [ 'file1.jpg', 'file1-thumb.jpg', 'file2.jpg', 'file2-thumb.jpg' ]

然后你可以得到一个包含单词thumb的 not 的文件列表,如下所示:

not_thumb_filenames = [ filename for filename in filenames if not 'thumb' in filename ]

这就是我们所说的list comprehension,基本上是简写:

not_thumb_filenames = []
for filename in filenames:
  if not 'thumb' in filename:
    not_thumb_filenames.append(filename)

这个简单的任务不一定需要正则表达式。