【问题标题】:Regex match for optional file extension可选文件扩展名的正则表达式匹配
【发布时间】:2012-06-05 10:38:10
【问题描述】:

我正在使用 Python 中的正则表达式从文本中提取部分 URL。我正在寻找的 URL 来自一组有限的模式,所以感觉就像我应该能够在正则表达式中处理它们。我要提取的是文件名的第一部分(以下所有示例中的“some.file.name”),其中可以包括点、字母和数字。

这些是 URL 可以采用的形式:

http://www.example.com/some.file.name.html
http://www.example.com/some.file.name_foo.html
http://www.example.com/some.file.name(123).html
http://www.example.com/some.file.name_foo(123).html
http://www.example.com/some.file.name
http://www.example.com/some.file.name_foo
http://www.example.com/some.file.name(123)
http://www.example.com/some.file.name_foo(123)

我认为我对这个正则表达式非常满意:

http://www\.example\.com/([a-zA-Z0-9\.]+)(_[a-z]+)?(\(\d+\))?(\.html)?

但是当 URL 类似于列表中的第一个时,它会在匹配中包含“.html”。有什么方法可以阻止这种情况,还是正则表达式的基本限制?

我很高兴删除代码中的扩展名,因为它始终是相同的,并且永远不会作为文件名的一部分有效,但将其作为正则表达式匹配的一部分会更简洁。

编辑:

我要强调的是,这些 URL 位于正文中。我无法保证它们之前或之后是否有字符,或者这些字符可能是什么。我认为可以安全地假设它们不会是数字、字母、下划线或圆点。

【问题讨论】:

    标签: python regex url python-2.7


    【解决方案1】:

    正则表达式默认匹配greedy

    试试这个正则表达式:

    ^http://www\.example\.com/([a-zA-Z0-9\.]+?)(_[a-z]+)?(\(\d+\))?(\.html)?$
    

    请注意添加的额外? 不会捕获第一部分中的.html。它使第一组捕获尽可能少地匹配,而不是尽可能多地匹配。如果没有?.html 将包含在第一个组中,因为其他组是可选的,并且贪婪匹配会尝试尽可能“早”匹配。

    附:另请注意,我使用^$ 锚定了正则表达式以始终匹配整行。

    【讨论】:

    • 不幸的是,文件名后面的所有组都是可选的,使用 ? 在这里只会给我文件名的第一个字母,因为没有什么可以“拉”正则表达式的末尾网址。
    • 我的下一个想法是使用单词边界 (\b) 将正则表达式拉到 URL 的末尾。当然这不起作用,因为. 算作单词边界。
    • 这也是我添加$ 符号的原因。你也复制了吗?在某些语言中,“匹配”意味着^$,而不是开放式的“搜索”。不过,我更喜欢^$ 的显式方式。但是我还没有测试过第一个问号是否足以使最后的可选组更强大。但它应该是“贪婪的可选”?
    • 如果我只是自己处理 URL,那将是可行的,遗憾的是我正在从文本正文中提取它们。
    • 是的,“贪婪可选”是对我所追求的东西的非常准确的描述。
    【解决方案2】:

    您可以将 .html 扩展名指定为非捕获组:

    http://www\.example\.com/([a-zA-Z0-9\.]+)(_[a-z]+)?(\(\d+\))?(?=(\.html)?)
    

    【讨论】:

    • 遗憾的是,这不是这里的问题。我的问题是“.html”被包含在第一组中,而不是它被捕获在自己的组中。
    • 好的,然后尝试一个后缀组: (?=(\.html)?) 在末尾而不是 ?:
    • burkeware.com/software/regex_playground.html 尝试这个仍然包括.html 在第一个示例的情况下。这可能与语言有关吗?
    【解决方案3】:

    在我看来,您并不关心文件扩展名。您只想提取文件名。

    试试这个:

    http://www\.example\.com/([\w]+.[\w]+.[\w()]+)
    

    在 PHP 中,我使用了 preg_match_all($regex, $str, $matches),它返回类似这样的内容。

    Array
    (
        [0] => Array
            (
                [0] => http://www.example.com/some.file.name
                [1] => http://www.example.com/some.file.name_foo
                [2] => http://www.example.com/some.file.name(123)
                [3] => http://www.example.com/some.file.name_foo(123)
                [4] => http://www.example.com/some.file.name
                [5] => http://www.example.com/some.file.name_foo
                [6] => http://www.example.com/some.file.name(123)
                [7] => http://www.example.com/some.file.name_foo(123)
            )
    
        [1] => Array
            (
                [0] => some.file.name
                [1] => some.file.name_foo
                [2] => some.file.name(123)
                [3] => some.file.name_foo(123)
                [4] => some.file.name
                [5] => some.file.name_foo
                [6] => some.file.name(123)
                [7] => some.file.name_foo(123)
            )
    
    )
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多