提取文件路径的通用正则表达式(非URL)。

7

我正试图使用Python解析文件中的url和文件路径。我已经有一个url正则表达式。

问题

我需要一个从字符串中提取文件路径的正则表达式模式。要求:

  • 独占的(不包括urls)
  • 与操作系统无关,即支持Windows和UNIX样式的路径,例如:C:\\\/)
  • 所有类型的路径,即绝对路径和相对路径,例如:/../)

请通过修改下面的尝试或建议一个更好的正则表达式模式来帮助我。

尝试

以下是我目前拥有的正则表达式

(?:[A-Z]:|\\|(?:\.{1,2}[\/\\])+)[\w+\\\s_\(\)\/]+(?:\.\w+)*

描述

  • (?:[A-Z]:|\\|(?:\.{1,2}[\/\\])+): 匹配前面的任何驱动器号、反斜杠或点路径
  • [\w+\\\s_\(\)\/]+: 匹配任何类似路径的字符-字母数字、斜线、括号、下划线等
  • (?:\.\w+)*: 可选扩展名

结果

enter image description here

注意: 我已经用Python和re模块确认了这些结果。

期望

该正则表达式满足我的大部分要求,即排除URL并提取大多数文件路径。但是,我希望匹配所有路径(包括以单个斜杠开头的UNIX样式路径,例如/foo/bar.txt),而不匹配URL。

研究

我没有找到通用解决方案。大多数工作往往满足特定情况。

SO 帖子

外部网站


如果要实现可移植性,可以匹配前面的字符。也不应该使用非捕获组。请尝试访问 https://regex101.com/r/IsmBeL/8。 - revo
或者添加另一个负回顾后发生的交替以匹配前两个路径。https://regex101.com/r/5Dyith/1 - The fourth bird
1
好的,这将会很有趣。command.com实际上是一个文件名和一个互联网主机。 - melpomene
2
为了匹配UNIX中的有效文件名,您可以执行以下操作:'\0' not in filename and filename[-1] != '/'。唯一的限制是文件名不能包含\0,文件名中不能包含/(显然其绝对路径将包含/)。 (我可能会补充说,使用普通API,您实际上无法在文件名的名称部分中包含/,除非将其放置在名称的末尾...在其他位置,它将被解释为路径中的分隔符)。 - Bakuriu
@melpomene 抱歉,我没有理解您的观点。 - revo
显示剩余9条评论
1个回答

3

你可以将问题分为三种不同的模式: (请注意,我没有对路径/文件名中的所有字符排除进行实现)

  • 非引用的Windows路径
  • 引用的Windows路径
  • Unix路径

这样会得到如下结果:

((((?<!\w)[A-Z,a-z]:)|(\.{1,2}\\))([^\b%\/\|:\n\"]*))|("\2([^%\/\|:\n\"]*)")|((?<!\w)(\.{1,2})?(?<!\/)(\/((\\\b)|[^ \b%\|:\n\"\\\/])+)+\/?)

分解如下:

Wind-Non-Quoted: ((((?<!\w)[A-Z,a-z]:)|(\.{1,2}\\))([^\b%\/\|:\n\"]*))
Wind-Quoted:     ("\2([^%\/\|:\n\"]*)")
Unix:            ((?<!\w)(\.{1,2})?(?<!\/)(\/((\\\b)|[^ \b%\|:\n\"\\\/])+)+\/?)


Wind-Non-Quoted:
    prefix: (((?<!\w)[A-Z,a-z]:)|(\.{1,2}\\))
         drive: ((?<!\w)[A-Z,a-z]:) *Lookback to ensure single letter*
      relative: (\.{1,2}\\))
      path: ([^\b%\/\|:\n\"]*))     *Excluding invalid name characters (The list is not complete)*

Wind-Quoted:
    prefix: \2                *Reuses the one from non-Quoted*
      path: ([^%\/\|:\n\"]*)  *Save as above but does not exclude spaces*

Unix:
    prefix: (?<!\w)(\.{1,2})?                . or .. not preceded by letters
      path: (?<!\/)                          repeated /name (exclusions as above)
            (\/((\\\b)|[^ \b%\|:\n\"\\\/])+) not preceded by /
            \/?                              optionally ending with /

            *(excluding the double slashes is intended to prevent matching urls)*

我很欣赏你的工作。 你的方法确实与我大部分测试(https://regex101.com/r/qFDLwB/1/)相匹配。 然而,大多数情况下都会进行多个捕获。 相反,我认为你需要多个非捕获组和一个捕获组来提取一个连贯的文件路径。请参考备选方案:https://regex101.com/r/IsmBeL/26。此外,您能否解决剩余的边缘情况? - pylang

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