正则表达式以匹配除文件及其父目录以外的路径

时间:2019-07-03 09:36:38

标签: regex perl

我正在尝试编写一个与文件路径匹配但不包含文件名及其父目录的表达式。这是我的测试字符串:

file/in/some/dir1/file1.txt
file/in/some/dir2/file1.txt
file/in/some/dir2/file2.txt
file/in/some/other/dir/file1.txt

我希望正则表达式匹配的是:

file/in/some
file/in/some
file/in/some
file/in/some/other

我尝试了各种否定的前瞻性尝试,但没有成功。我所能想到的就是一个与我想要的匹配项(\w+\/\w+\.\w+)完全相反的表达式。有了这个,我得到了文件名及其父目录,但是我不知道如何“反转”结果。

谢谢。

5 个答案:

答案 0 :(得分:2)

您与“正好匹配”正则表达式非常接近,只需要捕获字符串的 other 部分:

m{(.*)/\w+/\w+\.\w+$}

我也对其进行了修改,以使比赛的未捕获部分必须以/开头(否则结果错误),使用m{}而不是//分隔正则表达式,以便不需要转义正则表达式中的/字符(\/-“倾斜牙签综合症”),并将其锚定到字符串的末尾(这样就可以了)如果目录名称之一包含.,仍将正常工作。

全面测试实施:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my @paths = qw(
  file/in/some/dir1/file1.txt
  file/in/some/dir2/file1.txt
  file/in/some/dir2/file2.txt
  file/in/some/other/dir/file1.txt
);

for my $path (@paths) {
  $path =~ m{(.*)/\w+/\w+\.\w+$};
  say $1;
} 

输出:

file/in/some
file/in/some
file/in/some
file/in/some/other

答案 1 :(得分:1)

文件或目录名称不能包含斜杠。因此,路径的最后两个部分是/[^/]+/[^/]+$

#!/usr/bin/perl
use warnings;
use strict;

use Test::More tests => 4;

my %test = (
    'file/in/some/dir1/file1.txt'      => 'file/in/some',
    'file/in/some/dir2/file1.txt'      => 'file/in/some',
    'file/in/some/dir2/file2.txt'      => 'file/in/some',
    'file/in/some/other/dir/file1.txt' => 'file/in/some/other');

for my $path (keys %test) {
    is match($path), $test{$path}, $path;
}

sub match {
    my ($path) = @_;
    return ($path =~ m{(.*)/[^/]+/[^/]+$})[0]
}

答案 2 :(得分:0)

尝试以下模式:

(.*)/\w+\/\w+\.\w+

然后捕获第一组。

答案 3 :(得分:0)

这是完成任务的一种方法:

use strict;
use warnings;
use feature 'say';

while(<DATA>) {
    chomp;
    s~/[^/]+/[^/]+$~~;
    say;
}

__DATA__
file/in/some/dir1/file1.txt
file/in/some/dir2/file1.txt
file/in/some/dir2/file2.txt
file/in/some/other/dir/file1.txt

输出:

file/in/some
file/in/some
file/in/some
file/in/some/other

答案 4 :(得分:0)

这是另一种假设所有数据都在字符串中并使用超前正则表达式的方法:

my $files = "1: file/in/some/dir1/file1.txt
2: file/in/some/dir2/file1.txt
3: file/in/some/dir2/file2.txt
4: file/in/some/other/dir/file1.txt";
my @dirs = $files =~ m{((?:\w+/)+)(?=\w+\/\w+\.\w+)}g;
say for @dirs;

输出

file/in/some/
file/in/some/
file/in/some/
file/in/some/other/