基于斜杠分割Perl字符串

3

我是Perl的新手,所以这是一个基础问题。我有一个如下所示的字符串。我想从中取出日期,所以考虑使用斜杠进行拆分。

my $path = "/bla/bla/bla/20160306";
my $date = (split(/\//,$path))[3];#ideally 3 is date position in array after split
print $date;

然而,我并没有看到预期的输出,而是看到了数字5被打印出来。


1
当你不确定变量包含什么时:use Data::Dumper; print Dumper \@split; - TLP
3个回答

6

由于路径以模式/本身开头,split返回一个列表,其中第一个元素为空字符串(在第一个/左侧); 元素比原来多一个。因此,发布的代码错误计算了一个,并返回路径中倒数第二个元素(子目录),而不是日期。

如果日期始终是字符串中的最后一项,则可以选择最后一个元素。

my $date = (split '/', $path)[-1];

我在使用''作为分隔符,以免需要转义/。(然而,这可能会引起混淆,因为分隔符模式是一个正则表达式,而//表达了这一点,而''似乎只是引用一个字符串。)


这也可以用正则表达式来实现

my @parts = $path =~ m{([^/]+)}g;

这样就不会有初始空字符串了。或者,可以像上面那样从完整列表中挑选出最后一部分,使用 ($path =~ m{...}g)[-1],但如果您只需要最后一部分,则直接提取它即可。

my ($last_part) = $path =~ m{.*/(.*)};

在这里,“贪婪”的.*匹配字符串中的所有内容,直到下一个子模式(这里是/)的最后一个实例,因此使我们到达路径的最后一部分,然后进行捕获。正则表达式匹配运算符仅在列表上下文中返回其匹配项,因此需要左括号。

为什么要解析路径?因为有专门用于此目的的库。

将路径拆分为其组成部分的一种工具是 File::Specsplitdir

use File::Spec;

my @parts = File::Spec->splitdir($path);

如果路径以/开头,我们将再次获得第一个元素的空字符串(按设计,参见文档)。如果存在这种情况,则可以将其删除。
shift @parts if $parts[0] eq '';

同样地,最后一个元素也可以像其他示例中一样获得。


无法使用 '/',因为 '/' 需要作为字符串解析到函数中。 - Owl
@Owl “无法使用'/',因为'/'需要作为字符串解析到函数中”--我不明白这是什么意思?在第一个示例中,'/'是要拆分字符串的模式。它需要被“解析”成哪个“函数”?它是要处理的字符串的一部分,而split会将字符串分解成所有找到的'/'周围的部分。(这里的所有示例都经过测试并且有效,请尝试一下。) - zdim
我解决了这个问题,它需要在字符串中首先用 \ 进行分隔,然后再用 / 进行分隔。基本上有一个包含“/”的变量,它需要变成“/”才能正常工作。我毫不怀疑“/”会起作用,但显然在分割变量时不起作用。 - Owl
@Owl 我还是不太明白 - 如果split中的模式由其他字符而非/本身分隔,则我们不需要在模式中转义/(正如我在回答中所解释的那样?)。 因此,split m{/}很好,split m|/|split m#/#也是如此。 使用引号是特别允许的(因此不需要m),因此split'/'split"/"也可以。 现在,如果想要使用通常的/.../作为定界符,那么确实需要转义它,split /\//。 这就是你的意思吗? - zdim
@Owl split 函数的分隔符参数是一个正则表达式,因此需要按照语法规则进行处理。我在答案中添加了链接。除此之外,引号是特别允许的(在普通的正则表达式中,需要在前面加上 m,即 $v =~ m"pattern")。 - zdim

1

Simply bind it to the end:

(\d+)$
# look for digits at the end of the string

请查看regex101.com上的演示。捕获组只是为了澄清,但在这种情况下并不真正需要。

Perl中,这将是这样的(我是一个PHP / Python的人,所以当它很丑陋时请忍耐)

my $path = "/bla/bla/bla/20160306";
$path =~ /(\d+)$/;
print $1;

请看

在ideone.com上演示的{{link1:一个演示}}


0

试试这个

使用前瞻来完成它。通过分割捕获/。然后使用/替换数据以去除斜杠。

my $path = "/a/b/c/20160306";
my $date = (split(/(?=\/)/,$path))[3];
$date=~s/^\///;
print $date;

或者使用带有分组的模式匹配来完成它。

my $path = "/a/b/c/20160306";
my @data = $path =~m/\/(\w+)/g;
print $data[3];

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