我正在尝试编写一个正则表达式,它将使用匹配组解析完全限定路径的目录和文件名。
所以...
/var/log/xyz/10032008.log
会识别group 1 to be "/var/log/xyz"
和group 2 to be "10032008.log"
看起来很简单,但我不能让匹配的小组为我的生活工作。
注意:正如一些受访者所指出的,这可能不是正常表达的好用。通常我更喜欢使用我正在使用的语言的文件API。我实际上要做的事情比这更复杂但是要解释起来要困难得多,所以我选择了一个每个人都熟悉的域名,以便最简洁地描述根本问题。
答案 0 :(得分:30)
试试这个:
^(.+)/([^/]+)$
答案 1 :(得分:16)
支持使用non-capturing groups的正则表达式的语言:
((?:[^/]*/)*)(.*)
我将通过爆炸来解释这个粗糙的正则表达式......
(
(?:
[^/]*
/
)
*
)
(.*)
这些部分意味着什么:
( -- 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
答案 2 :(得分:8)
大多数语言都有路径解析功能,这些功能已经为您提供了这些功能。如果你有这种能力,我建议你免费使用免费提供给你的东西。
假设/是路径分隔符......
^(.*/)([^/]*)$
第一组将是目录/路径信息,第二组将是文件名。例如:
答案 3 :(得分:4)
用什么语言?为什么要使用正则表达式完成这个简单的任务?
如果必须:
^(.*)/([^/]*)$
为您提供您想要的两个部分。您可能需要引用括号:
^\(.*\)/\([^/]*\)$
取决于您的首选语言语法。
但我建议你只使用你的语言的字符串搜索功能找到最后一个“/”字符,然后在该索引上拆分字符串。
答案 4 :(得分:1)
这个怎么样?
[/]{0,1}([^/]+[/])*([^/]*)
确定性:
((/)|())([^/]+/)*([^/]*)
严格:
^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$
答案 5 :(得分:0)
试试这个:
/^(\/([^/]+\/)*)(.*)$/
但是它会在路径上留下尾部斜杠。
答案 6 :(得分:0)
答案 7 :(得分:0)
我通过反复试验方法进行了一些研究。发现* nux机器中键盘上所有可用的值都可以作为文件或目录,但'/'除外。
我使用touch命令为后面的字符创建文件,并创建了一个文件。
(下面用逗号分隔的值)
'!','@','#','$',“''','%','^','&','*','(',')','','''' ,'\','-',',','[',']','{','}','`','〜','>','<','=',' +',';',':','|'
仅当我尝试创建'/'(因为它是根目录)和文件名容器/
时,它失败了,因为它是文件分隔符。
当我执行.
时,它更改了当前目录touch .
的修改时间。但是,可以使用file.log。
当然,a-z
,A-Z
,0-9
,-
(连字符),_
(下划线)应该可以工作。
因此,根据上述推理,我们知道文件名或目录名可以包含除/
前斜杠之外的任何内容。因此,我们的正则表达式将由文件名/目录名中不存在的内容派生。
/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/
root
目录开始如果目录是绝对路径,则目录可以以/
开头,而相对目录则可以以目录名开头。因此,请寻找出现次数为零或一次的/
。
/(?P<filepath>(?P<root>[/]?)(?P<rest_of_the_path>.+))/
接下来,目录及其子目录始终由/
分隔。目录名称可以是/
以外的任何名称。我们先匹配/ var/。
/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^\/]+/)(?P<rest_of_the_path>.+))/
接下来,让我们匹配所有目录
/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^\/]+/)+)(?P<rest_of_the_path>.+))/
在这里,single_dir为yz/
,因为首先匹配var/
,然后找到下一个相同模式的出现,即log/
,然后发现下一个相同模式的{{1 }}。因此,它显示了模式的最后一次出现。
现在,我们知道我们永远不会使用诸如single_dir,filepath,root之类的组。因此,让我们清理一下。
让我们将它们分组,但是不要捕获这些分组。
rest_of_the_path只是文件名!因此,将其重命名。而且文件名中不会包含yz/
,因此最好保留/
[^/]
这使我们得到最终结果。当然,还有其他几种方法可以执行此操作。我只是在这里提到一种方法。
/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/
表示字符串以
开头
^
表示按组名称捕获组。我们有两个组,组名分别为(?P<dir>pattern)
和dir
file
表示不考虑此组或不捕获该组。
(?:pattern)
表示匹配零或一。
?
表示匹配一个或多个
+
表示匹配除正斜杠([^\/]
)以外的任何字符
/
表示如果它是绝对路径,则可以以/开头,否则就不能。因此,请匹配[/]?
的零个或一个匹配项。
/
表示一个或多个不是正斜杠([^\/]+/
)的字符,其后是正斜杠(/
)。这将匹配/
或var/
。一次一个目录。
答案 8 :(得分:0)