题 用于解析目录和文件名的正则表达式


我正在尝试编写一个正在解析的正则表达式 目录和文件名 使用匹配组的完全限定路径

所以...

/var/log/xyz/10032008.log

会认出来的 group 1 to be "/var/log/xyz" 和 group 2 to be "10032008.log"

看似简单,但我不能让匹配的团队为我的生活工作。

注意:正如一些受访者所指出的,这可能不是正常表达的好用。通常我更喜欢使用我正在使用的语言的文件API。我实际上要做的事情比这复杂得多一些,但要解释起来要困难得多,所以我选择了一个每个人都熟悉的域名,以便最简洁地描述根本问题。


19
2017-10-03 21:44


起源




答案:


尝试这个:

^(.+)/([^/]+)$

26
2017-10-03 21:57



你不想让那些非贪婪(如果这个正则表达式可以处理那个),这样它就不必一直回溯到斜杠了吗? - Axeman
这假设有一个路径,而不仅仅是文件名。 - Travis Illig
它还遇到当前目录(。)和根目录(/)的问题。前者不是问题(完全限定的路径名​​不是以点开头);后者可能是。正则表达式也不处理..反向遍历 - 这可能没问题,因为完全限定可能意味着没有点点位。 - Jonathan Leffler
这也有效...... r'。* /(。*)$',组0将返回文件名。由于。*贪婪是默认的,它完成所有的工作。再假设有一条路。 - Paul Kenjora
^(.+)\/([^\/]+)$正斜杠必须逃脱? - Neil Agarwal


在支持正则表达式的语言中 非捕获组

((?:[^/]*/)*)(.*)

我将通过爆炸来解释这个粗糙的正则表达式......

(
  (?:
    [^/]*
    /
  )
  *
)
(.*)

这些部分意味着什么:

(  -- capture group 1 starts
  (?:  -- non-capturing group starts
    [^/]*  -- greedily match as many non-directory separators as possible
    /  -- match a single directory-separator character
  )  -- non-capturing group ends
  *  -- repeat the non-capturing group zero-or-more times
)  -- capture group 1 ends
(.*)  -- capture all remaining characters in group 2

为了测试正则表达式,我使用了以下Perl脚本......

#!/usr/bin/perl -w

use strict;
use warnings;

sub test {
  my $str = shift;
  my $testname = shift;

  $str =~ m#((?:[^/]*/)*)(.*)#;

  print "$str -- $testname\n";
  print "  1: $1\n";
  print "  2: $2\n\n";
}

test('/var/log/xyz/10032008.log', 'absolute path');
test('var/log/xyz/10032008.log', 'relative path');
test('10032008.log', 'filename-only');
test('/10032008.log', 'file directly under root');

脚本的输出......

/var/log/xyz/10032008.log -- absolute path
  1: /var/log/xyz/
  2: 10032008.log

var/log/xyz/10032008.log -- relative path
  1: var/log/xyz/
  2: 10032008.log

10032008.log -- filename-only
  1:
  2: 10032008.log

/10032008.log -- file directly under root
  1: /
  2: 10032008.log

12
2017-10-03 21:43





大多数语言都有路径解析功能,可以为您提供此功能。如果你有这种能力,我建议你免费使用免费提供给你的东西。

假设/是路径分隔符...

^(.*/)([^/]*)$

第一组将是目录/路径信息,第二组将是文件名。例如:

  • /foo/bar/baz.log:“/ foo / bar /”是路径,“baz.log”是文件
  • 富/ bar.log:“foo /”是路径,“bar.log”是文件
  • /富/酒吧:“/ foo /”是路径,“bar”是文件
  • /富/酒吧/:“/ foo / bar /”是路径,没有文件。

8
2017-10-03 21:48





什么语言?为什么要使用正则表达式完成这个简单的任务?

如果你 必须

^(.*)/([^/]*)$

为您提供您想要的两个部分。您可能需要引用括号:

^\(.*\)/\([^/]*\)$

取决于您的首选语言语法。

但我建议您只使用语言的字符串搜索功能找到最后一个“/”字符,并在该索引上拆分字符串。


4



许多框架(例如.NET / Python)具有从路径中分离文件名而无需手动搜索“/”字符的方法。这很好,因为这些工具通常与平台无关。 - Jordan Parmer
是的,但他尚未指定语言。如果是Python,我建议使用os.path.dirname和os.path.basename。 - tzot


那这个呢?

[/]{0,1}([^/]+[/])*([^/]*)

确定性:

((/)|())([^/]+/)*([^/]*)

严格:

^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$

1





尝试这个:

/^(\/([^/]+\/)*)(.*)$/

但是它会在路径上留下尾随斜线。


0





答案非常晚,但希望这会有所帮助

^(.+?)/([\w]+\.log)$

这使用懒惰检查 /,我刚刚修改了接受的答案

http://regex101.com/r/gV2xB7/1


0