38

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

所以...

/var/log/xyz/10032008.log

会承认group 1 to be "/var/log/xyz"group 2 to be "10032008.log"

看起来很简单,但我无法让匹配组为我的生活工作。

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

4

9 回答 9

43

试试这个:

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

编辑:转义正斜杠以防止在复制/粘贴正则表达式时出现问题

于 2008-10-03T21:44:56.760 回答
27

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

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

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

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

各部分的含义:

(  -- 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
于 2015-10-08T17:04:32.550 回答
11

大多数语言都有路径解析功能,它们已经为您提供了这个功能。如果您有能力,我建议您免费使用开箱即用的东西。

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

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

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

  • /foo/bar/baz.log:“/foo/bar/”是路径,“baz.log”是文件
  • foo/bar.log : "foo/" 是路径,"bar.log" 是文件
  • /foo/bar : "/foo/" 是路径,"bar" 是文件
  • /foo/bar/ : "/foo/bar/" 是路径,没有文件。
于 2008-10-03T21:57:44.737 回答
5

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

如果你必须

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

给你你想要的两个部分。您可能需要引用括号:

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

取决于您喜欢的语言语法。

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

于 2008-10-03T21:43:26.137 回答
3

推理:

我通过试错法做了一些研究。发现键盘中可用的所有值都可以作为文件或目录,除了 *nux 机器中的“/”。

我使用 touch 命令为以下字符创建文件,它创建了一个文件。

(下面的逗号分隔值)
'!'、'@'、'#'、'$'、"'"、'%'、'^'、'&'、'*'、'('、')'、 ' ', '"', '\', '-', ',', '[', ']', '{', '}', '`', '~', '>', '<' , '=', '+', ';', ':', '|'

仅当我尝试创建“/”(因为它是根目录)和文件名容器时它才失败,/因为它是文件分隔符。

.当我这样做时,它改变了当前目录的修改时间touch .。但是,file.log 是可能的。

当然,a-z, A-Z, 0-9, -(hypen), _(underscore) 应该可以工作。

结果

因此,通过上述推理,我们知道文件名或目录名可以包含除/正斜杠之外的任何内容。因此,我们的正则表达式将由文件名/目录名中不存在的内容派生。

/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/

一步一步的正则表达式创建过程

模式说明

步骤 1:从匹配root目录开始

/目录可以以绝对路径开头,目录名可以以相对路径开头。因此,寻找/零次或一次出现。

/(?P<filepath>(?P<root>[/]?)(?P<rest_of_the_path>.+))/

在此处输入图像描述

步骤2:尝试找到第一个目录。

接下来,一个目录和它的子目录总是用 . 分隔/。目录名称可以是除/. 让我们先匹配/var/。

/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^\/]+/)(?P<rest_of_the_path>.+))/

在此处输入图像描述

步骤 3:获取文件的完整目录路径

接下来,让我们匹配所有目录

/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^\/]+/)+)(?P<rest_of_the_path>.+))/

在此处输入图像描述

在这里, single_dir 是yz/因为,首先它匹配var/,然后它找到下一次出现的相同模式,即log/,然后它找到下一次出现的相同模式yz/。因此,它显示了模式的最后一次出现。

第 4 步:匹配文件名并清理

现在,我们知道我们永远不会使用像 single_dir、filepath、root 这样的组。因此,让我们清理一下。

让我们将它们保留为组,但不要捕获这些组。

而 rest_of_the_path 只是文件名!所以,重命名。而且文件的名称中不会有/,所以最好保留[^/]

/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/

这给我们带来了最终的结果。当然,还有其他几种方法可以做到。我只是在这里提到一种方式。

在此处输入图像描述

上面使用的正则表达式规则在此处列出

^表示以组名开头的字符串
(?P<dir>pattern)表示捕获组。我们有两个带有组名的组dirfile
(?:pattern)意味着不考虑这个组或非捕获组。
?表示匹配零或一。 +表示匹配一个或多个 [^\/]表示匹配除正斜杠 ( /)之外的任何字符

[/]?意味着如果它是绝对路径,那么它可以以 / 开头,否则它不会。因此,匹配零个或一个/.

[^\/]+/表示一个或多个不是正斜杠 ( /) 后跟正斜杠 ( ) 的字符/。这将匹配var/xyz/。一次一个目录。

于 2019-04-09T19:42:07.920 回答
2

那这个呢?

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

确定性:

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

严格的 :

^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$
于 2011-12-03T18:08:44.140 回答
1

一个很晚的答案,但希望这会有所帮助

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

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

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

于 2014-10-29T16:21:45.987 回答
0

试试这个:

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

不过,它会在路径上留下斜杠。

于 2008-10-03T21:48:47.687 回答
0

给定一个示例上传文件夹 URL:

https://drive.google.com/drive/folders/14Q6d-KiwgTKE-qm5EOZvHeX86-Wf9Q5f?usp=sharing

正则表达式模式是:

[-\w]{25,}   

此模式也适用于 Google 表格以及 Excel 中的自定义函数:

=REGEXEXTRACT(N2,"[-\w]{25,}")

结果是:14Q6d-KiwgTKE-qm5EOZvHeX86-Wf9Q5f

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

于 2021-08-05T10:44:13.727 回答