【问题标题】:Make regex match dotfiles accurately使正则表达式准确匹配点文件
【发布时间】:2017-03-20 20:39:35
【问题描述】:

所以我已经达到了我的正则表达式能力的极限。我在这里有一个 python 正则表达式来匹配文件路径或文件 uri 与各个部分的命名捕获组。它似乎是工作文件,除了点文件。

MATCH_PATH = re.compile(
    r"^(?P<uri>file://)?" +             # optional file uri
    r"(?P<path>(?:/?[A-Z]{1}:)?" +      # start of path capture, optional windows top-level directory
    r"[\\/]?" +                         # optional start separator
    r"(?:[\w \-\.]+[\\/])+)" +          # path
    r"(?P<filename>[\w \-]+)?" +        # optional filename
    r"\.?(?P<extension>[a-zA-Z0-9]+)?$" # extension optional
)

我可以让它在扩展部分的. 之后通过removing the optional qualifier ? 匹配点文件,但是它不能匹配没有扩展名的文件(例如makefile)或目录。我尝试放置non-capturing group around the dot and the extension group with the optional qualifier,但没有成功:扩展名与文件名分组。我可以调整它以在所有情况下正确匹配扩展名和名称,同时仍然匹配目录吗?

应匹配的输入示例:

/foo/bar.txt
/foo/bar/
/foo/makefile
./foo.txt
/foo/._bar.txt
foo/bar.txt
D:\foo\bar.m3u
file:///var/www/html/index.html
file:///C:/users/me/My Documents/index.html

更新

还需要正确匹配

/foo/bar.tar.gz
/foo/._bar.tar.gz

扩展名为tar.gz,名称分别为bar._bar。如果这对于正则表达式来说太复杂了,请告诉我,我可以编写程序代码来拆分和处理。

【问题讨论】:

  • 您错过了可能的 . (点)在文件名组中。

标签: python regex python-3.x


【解决方案1】:

您可以很好地在前瞻中使用命名的捕获组,如下所示:

^
(?P<uri>file://)?
(?P<path>(?:/?[A-Z]{1}:)?           # start of path capture, optional windows top-level directory
[\\/]?                              # optional start separator
(?:[-. \w]+[\\/])+)                 # path
(?P<filename>\.?[^.]+?(?=\.(?P<extension>.+$)|$))?

a demo on regex101.com


我唯一改变的是filename组:
(?P<filename>\.?[^.]+?(?=\.(?P<extension>.+$)|$))

它使用带有正向前瞻的惰性点星,查找.some_extension(然后将其保存到extension)或行尾。

【讨论】:

  • 这很好,但在例如失败/foo/bar.tar.gz,我已更新问题以反映此要求。
  • 然后您需要定义可以出现哪些文件扩展名 - 对于正则表达式引擎,.bar.txt 中的 _bar.bar.txtbar.tar.gz 中的 .tar.gz 相同。
  • 它可以是任何东西,而且我们可能已经超出了正则表达式所能做的范围(在这种情况下,我将手动解析它)。基本上我希望第一个点之前的所有内容都是名称(除非第一个字符是一个点,即一个点文件),之后的所有内容都是扩展名。
  • 所以foo/bar.tar.gz 的名称为bar,扩展名为tar.gzfoo/._bar.tar.gz 的名称为._bar,扩展名为tar.gz
  • @JaredSmith:查看更新的答案和演示,然后使用否定类。
【解决方案2】:

我设法对其进行了一些清理,并让正则表达式与您的所有示例数据相匹配。 Here 是否有测试环境,因此您可以看到它与不同的捕获组一起工作。

^(?P<uri>file:\/\/\/)?
(?P<path>(?:\/|\\|\.)?(?:[A-Z]:(?:\/|\\))?(?:[\w \-\.]+[\/\\])+)
(?P<file>\.?[\_\w ]+)?
(?P<extension>\.[\w\d]+)?$

我认为您所拥有的主要问题是您没有将前面的. 包含在file 捕获组中的可能性。为了解决这个问题,我将它添加为 . 之前的可选 file 组并解决了这个问题。

我所做的另一个小改动是将扩展程序前面的 . 包含在 extension 组中,但如果您愿意,可以进行更改。

【讨论】:

  • 嗯,现在试试。我以为我以前保存过它。
  • 这里有几个缺陷,尤其是字符类\w 是否包含\d。此外,Python 中的正斜杠不需要转义。点或减号也不需要在字符类中转义。多合一:regex101.com/r/DikDxF/4
  • 这有一些问题...它捕获了我不想要的扩展名中的点,它在文件 uri 中添加了一个额外的斜杠,并在扩展名中添加了 \w与我原来的分组不同,允许使用下划线。不过,+1 表示您付出了坚实的努力。
猜你喜欢
  • 2022-01-13
  • 2011-05-15
  • 2013-02-11
  • 1970-01-01
相关资源
最近更新 更多