Python中的正则表达式无法匹配字符串末尾

29

我刚学Python,但好像想不出正则表达式的用法。

r1 = re.compile("$.pdf")
if r1.match("spam.pdf"):
    print 'yes'
else:
    print 'no'

我希望这段代码能够打印出 'yes',但是它固执地打印出了 'no'。我还尝试了以下每一种方法:

r1 = re.compile(r"$.pdf")

r1 = re.compile("$ .pdf")

r1 = re.compile('$.pdf')

if re.match("$.pdf", "spam.pdf")

r1 = re.compile(".pdf")

还有无数其他变体。我已经搜索了相当长时间,但找不到/理解任何能解决我的问题的东西。有人能够帮助一个新手吗?


6
这与Python无关...你需要做一个正则表达式的教程... - Joran Beasley
正则表达式入门... http://www.aivosto.com/vbtips/regex.html - Austin Henley
6个回答

63
你已经尝试了所有的变化,除了那个有效的。 $ 应该放在模式的末尾。此外,你需要转义句点,以便它实际上匹配一个句点(通常它匹配任何字符)。
r1 = re.compile(r"\.pdf$")

然而,更加简单和清晰的方法是使用字符串的.endswith()方法:

if filename.endswith(".pdf"):
    # do something
那样,您就不必解密正则表达式才能理解发生了什么。

8
你可能正在使用.match()来检查是否匹配。你需要使用.search(),因为.match()仅检查字符串开头的内容。 - kindall
1
@user1634426 你可能想使用 re.search 而不是 re.match。 - Vatine
你如何修改它以检查多个扩展名?类似这样:filename.endswith("html|css|js") - budji
3
很抱歉很晚才回复(错过了时间)。.endswith() 可以接受一个字符串元组作为参数,匹配元组中任何一个字符串。例如 filename.endswith((".html", ".css", ".js")) - kindall
@kindall 当然是Python。每种编程语言都有自己的特定模式,而Python必须有它自己的逻辑:\ - t3chb0t
显示剩余2条评论

32

re.match()和re.search()的行为

它们之间有一个重要的区别:re.match()检查字符串的开头,你最有可能在寻找re.search()

这两种方法的比较在Python文档的章节“search() vs. match()”中清楚地展示了出来

正则表达式中的特殊字符

正则表达式中字符的含义与你尝试使用它的含义不同(详见正则表达式语法):

  • ^匹配开头:

    (插入符号)匹配字符串的开始,在MULTILINE模式下也会匹配每个换行符后面的位置。

  • $匹配结尾:

    匹配字符串的结束或者倒数第二个位置是换行符,而且在MULTILINE模式下,也会匹配换行符前面的位置。foo可以匹配“foo”和“foobar”,而正则表达式foo$只会匹配“foo”。更有趣的是,在'foo1\nfoo2\n'中查找foo.$,通常会匹配到“foo2”,但在MULTILINE模式下会匹配到“foo1”;在'foo\n'中查找单个$会找到两个(空的)匹配项:一个是在换行符之前,一个是在字符串末尾。

完整答案

你正在寻找的解决方案可能是:

import re
r1 = re.compile("\.pdf$")  # regular expression corrected
if r1.search("spam.pdf"):  # re.match() replaced with re.search()
    print "yes"
else:
    print "no"

这个函数会检查字符串是否以".pdf"结尾。与kindall的答案使用.endswith()相同,但如果kindall的答案适用于你,最好选择它(因为你可能根本不需要正则表达式)。


8

您的问题

$ 表示字符串末尾。因此,您需要一个像\.pdf$这样的正则表达式来匹配:

  1. 一个点(.),因为它是正则表达式中的特殊字符,所以需要转义。
  2. 字符串 "pdf"
  3. 字符串末尾。

进一步阅读

正则表达式超越了语言,Python或其他语言,因此您应该首先阅读一些关于它们的教程。可以考虑阅读regular-expressions.info。实际上这不是一个Python问题,而是一个基本的正则表达式问题。


1
正则表达式$.pdf的意思是“找到字符串的结尾,然后找到任何字符并超出字符串的任何字符,找到一个p、d和f”。
按照这种写法,它无法匹配任何内容。
但是,pdf$可以匹配。
在这种特定情况下,您可能还想进行搜索而不是匹配,因为我认为匹配本质上是锚定在字符串的开头。

1

我看到了两个快速的替代方案:

  • re.match(pattern='.*pdf$', string='filename.pdf')

    使用这种解决方案,我们必须指定我们不关心字符串如何开始。但是我们不能省略表达式在开头。 当使用re.match()时,您必须确保提供一个整个字符串有效的正则表达式,即从索引0开始查看https://docs.python.org/3/howto/regex.html#match-versus-search

  • re.search(pattern='\.pdf$', string='filename.pdf')

    我们不关心字符串如何开始,我们只是搜索以扩展名结尾的字符串

已经有答案被接受了,但我个人需要查看官方文档才能明确。


-1
#This will work for regular expression
r1 = re.compile(r".+\.pdf$")
if r1.match("spam.pdf"):
    print 'yes'
else:
    print 'no'
#alternative soln
if filename.endswith(".pdf"):
    print 'yes'
else:
    print 'no

1
这个有什么额外的东西,已经被接受的答案没有提到吗? - Henry Woody
r1 = re.compile(".pdf$") 这个只接受像“.pdf”这样的模式,不接受字符串“filename.pdf”。但是 r1 = re.compile(r".+.pdf$") 则可以。filename.endswith(".pdf") 是正确的。 - Anirban Hati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接