【问题标题】:regex match nothing at the end of string正则表达式在字符串末尾不匹配
【发布时间】:2019-12-18 15:04:46
【问题描述】:

我正在尝试匹配文件名中由点分隔的任意数量的文字 # 符号。文字 # 符号必须在两边用点分隔,除非它是文件名的最后一个元素。我可以创建一个模式来执行第一个(匹配由点包围的任何文字 # 符号),但我不能这样做,同时还允许第二个(以文字 # 符号结尾且没有尾随点的文件名)。

例如,以下将匹配:

bob.#
bob.#.
bob.#.exr
bob.##.mary.tif
bob.####.png

而以下不匹配:

bob.#string.exr
bob.string#.exr

到目前为止,我的模式(在 python 中表示为原始字符串)是:

(.*)(\.#+)((?:\.+.*|$))

不幸的是,它与我列表中的第一项不匹配:bob.#

我原以为最后一个非捕获组基本上会读作:

匹配一个文字点,后跟 0 个或多个字符

匹配字符串的结尾

但在 regexr.com 中对其进行测试显示它与 bob 不匹配。#

提前感谢任何线索!

【问题讨论】:

    标签: python regex regex-group


    【解决方案1】:

    您的表达式似乎工作得很好,我仍然会将其修改为类似于以下的表达式:

    import re
    
    regex = r"^([^.]*)(\.#+)(\..*)?$"
    
    test_str ="""
    bob.#
    bob.#.
    bob.#.exr
    bob.##.mary.tif
    bob.####.png
    Whereas the following would not match:
    
    bob.#string.exr
    bob.string#.exr
    
    """
    
    print(re.findall(regex, test_str,re.M))
    

    输出

    [('\nbob', '.#', ''), ('bob', '.#', '.'), ('bob', '.#', '.exr'), ('bob', '.##', '.mary.tif'), ('bob', '.####', '.png')]
    

    如果您想探索/简化/修改表达式,它已经 在右上角的面板上进行了解释 regex101.com。如果你愿意,你 也可以在this link看,怎么搭配 针对一些样本输入。


    正则表达式电路

    jex.im 可视化正则表达式:

    【讨论】:

    • 现在好了。我现在觉得有点傻。我习惯于首先在 regexr.com 中尝试我的正则表达式,然后在将它们转移到我的代码中之前在那里对其进行磨练。看起来这种模式这次可能让我失望了。谢谢!编辑:看起来正则表达式喜欢你改进的模式。
    【解决方案2】:

    ^\w*?\.(#+)(\.\w*?)*?$

    此正则表达式匹配一个点前面的任意数量的单词字符(包括无字符),匹配一个或多个八角符号,然后可选地匹配一个点和更多单词/字符。

    ^\w*?\.(#+)(\.\w*?)*?$
    
    ^                         anchor to the start of the line
     \w*?                     get as many word characters as you want, but as few as you need
         \.                   match . literally
           (#+)               match one or more # literally. grouped for your convenience if you want to count how many times they appear or something.
               (      )*?     match zero or more of this group:
                \.            a literal dot...
                  \w*?        ...and zero or more word characters, as few as needed.
                         $    ensure the string ends with this group.
    

    Try it here!

    关于这个正则表达式的几点说明:

    • 只有当行中没有其他字符串时,它才会匹配您的字符串。
    • 八爪鱼是分组的,以后可以提取出来进行计数(或任何你想要的)。
    • \w* 通常比.* 更安全、更快速——它专门查找单词字符a-z, A-Z, 0-9, _ 而不是任何符号。作为一般规则,如果你可以让你的正则表达式更具体,你应该,以免你冒着catastrophic backtracking!的恐怖风险

    【讨论】:

    • 感谢超级清晰的解释和分解!很高兴了解 \w 在速度方面的工作原理。在我的特殊情况下,我需要匹配文件名中可能出现的任何字符,包括一些非常深奥的字符,但非常感谢您的警告(和链接)。
    • 您不必使\w*? 不贪心,因为它不能越过点,您不必像您一样使*?$ 组的最后一次迭代不贪心断言字符串的结尾。
    • @Thefourthbird 可靠的建议 - 当我减少非贪婪时,它也节省了 39 个步骤。当我制作未来的正则表达式时,我会记住这一点。
    【解决方案3】:

    如果您希望它匹配整个元序列,这里有一个:

    import re
    
    pattern = re.compile(r'(\w+\.\#+(?:\.|$)\w*\.*\w*)')
    test = ['bob.#', 'bob.#.', 'bob.#.exr', 'bob.##.mary.tif', 'bob.####.png', 'bob.#string.exr', 'bob.string#.exr']
    for t in test:
        print(re.findall(pattern, t))
    

    输出:

    ['bob.#']
    ['bob.#.']
    ['bob.#.exr']
    ['bob.##.mary.tif']
    ['bob.####.png']
    []
    []
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 2010-11-23
      相关资源
      最近更新 更多