regex 如果我没有在Python正则表达式中显式地指定一个空格字符,为什么它仍然能找到正确的匹配?

tf7tbtn2  于 2022-11-18  发布在  Python
关注(0)|答案(1)|浏览(82)

[已编辑]问题:示例中的代码Option 2(* 页面底部 )如何匹配带有空格字符的输入字符串,而不在正则表达式中显式定义空格字符( 我认为它一定是以某种方式这样做的,否则它不会找到匹配项,并产生正确的输出-我只是不知道它是什么 *)
**程序结构:*给定HTML文本的输入字符串( 根据下面的示例A和B *),从嵌入的HTML文本中提取Youtube URL,然后以指定格式打印URL。

以下是用于测试函数解析的2个HTML输入字符串:

示例A:

<iframe src="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>

示例B:

<iframe width="560" height="315" src="https://www.youtube.com/embed/xvFZjo5PgG0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

在这些HTML字符串(上面)中找到的URL可以是以下3种格式中的任何一种,因此正则表达式应该能够选择性地匹配其中之一:“http://"、“https://”或“https://www

http://youtube.com/embed/xvFZjo5PgG0
https://youtube.com/embed/xvFZjo5PgG0
https://www.youtube.com/embed/xvFZjo5PgG0

两个输入字符串(Ex.A&Ex.B)在传递给分析时应生成以下输出:

https://youtu.be/xvFZjo5PgG0

**选项1:**根据下面的内容,当传递指定的输入字符串进行解析时,此解决方案代码正确返回预期的输出。此外,为了处理HTML输入字符串中的空格,此解决方案使用str.replace()函数直接清除输入,通过替换所有“空格”字符,如“〈iframe src”之间的空格...。因此,我没有在正则表达式中定义空格字符,因为它们已经从输入中清除。

import re

def main():
    print(parse(input("HTML: ").replace(" ","")))

def parse(s):
    if matches := re.search(r"^(?:<iframe[=\w\"]*src=)?\"(?:https?://)(?:www\.)?youtube\.com/embed/(\w*)\"(?:[\w=\";-]*></iframe>)?$", s):
        id = matches.group(1)
        url = f"https://youtu.be/{id}"
        return url

if __name__ == "__main__":
    main()

*选项2:这个解决方案 * 也 * 在传递输入字串(*Ex. AEx. B上述 )进行剖析时产生正确的输出。然而,在这个解决方案中,没有明确行程空白字符,不论是清除输入字串( 如选项1),或是在正则表达式中明确定义空白字符。然而,它 * 必须 * 以某种方式这样做,因为它仍然正确地符合含有空白字符的字串。

import re

def main():
    print(parse(input("HTML: ")))

def parse(s):
    if matches := re.search(r"(?:<iframe[=\w\"]*src=)?\"(?:https?://)(?:www\.)?youtube\.com/embed/(\w*)\"([\w=\";-]*></iframe>)?", s):
        id = matches.group(1)
        url = f"https://youtu.be/{id}"
        return url

if __name__ == "__main__":
    main()
  • 总而言之,考虑到没有显式处理空白字符,Option 2(上面)如何找到匹配(当传递字符串Ex. AEx. B时)并生成正确的输出?*
w8f9ii69

w8f9ii691#

我想你对两者的工作原理有一点误解,但是让我们从2开始,因为回答它的工作原理可以为1的工作原理提供一些启发。

为什么选项2有效?

下面的正则表达式(B):
(?:<iframe[=\w\"]*src=)?\"(?:https?://)(?:www\.)?youtube\.com/embed/(\w*)\"([\w=\";-]*></iframe>)?
实际上不处理空格,如果你在online regex tool中尝试一下,你会发现它实际上是这样匹配的:
示例A <iframe src="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>

  1. "https://www.youtube.com/embed/xvFZjo5PgG0"
  2. xvFZjo5PgG0
  3. ></iframe>
    示例B <iframe width="560" height="315" src="https://www.youtube.com/embed/xvFZjo5PgG0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  4. "https://www.youtube.com/embed/xvFZjo5PgG0"
  5. xvFZjo5PgG0
    字符串中的其他内容完全被忽略,但是由于你使用的是python re.search,当它搜索字符串时,你仍然会得到一个匹配。如果你使用re.match强制字符串从头开始匹配,它会中断。
    您可以通过将输入字符串简单地更改为"https://www.youtube.com/embed/xvFZjo5PgG0"来测试它,它仍然以完全相同的方式工作(获得所有完全相同的匹配)。
    实际上,在这个场景中,正则表达式的大部分是superflous的,繁重的工作由\"(?:https?://)(?:www\.)?youtube\.com/embed/(\w*)\"完成,其余的部分对于没有去掉空格的字符串没有任何作用,在执行re.search时也几乎没有任何作用。
    通过在这个正则表达式中抛出去掉空格的字符串,可以看到匹配是如何变化的:
    示例A <iframesrc="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>
  6. <iframesrc="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>
  7. xvFZjo5PgG0
    示例B <iframewidth="560"height="315"src="https://www.youtube.com/embed/xvFZjo5PgG0"title="YouTubevideoplayer"frameborder="0"allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture"allowfullscreen></iframe>
  8. <iframewidth="560"height="315"src="https://www.youtube.com/embed/xvFZjo5PgG0"title="YouTubevideoplayer"frameborder="0"allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture"allowfullscreen></iframe>
  9. xvFZjo5PgG0

那么,为什么选项1有效呢?

第一个选项起作用的原因是您要压缩所有内容并删除空格,这最终会使正则表达式的其余部分起作用。实际上,这两个选项的正则表达式的唯一真实的区别是,您re.search通过添加^$强制www.example.com充当re.match,从而强制匹配整个字符串。但它对去除了空格的字符串没有任何作用。

示例A <iframesrc="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>

  1. <iframesrc="https://www.youtube.com/embed/xvFZjo5PgG0"></iframe>
  2. xvFZjo5PgG0

示例B <iframewidth="560"height="315"src="https://www.youtube.com/embed/xvFZjo5PgG0"title="YouTubevideoplayer"frameborder="0"allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture"allowfullscreen></iframe>

  1. <iframewidth="560"height="315"src="https://www.youtube.com/embed/xvFZjo5PgG0"title="YouTubevideoplayer"frameborder="0"allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture"allowfullscreen></iframe>
  2. x1米25英寸

TL;DR:

它之所以有效,是因为re.search将在字符串的中间匹配,并且正则表达式(\"(?:https?://)(?:www\.)?youtube\.com/embed/(\w*)\")的唯一非可选部分永远不会有空格。

相关问题