我是Perl的新手,所以这是一个基础问题。我有一个如下所示的字符串。我想从中取出日期,所以考虑使用斜杠进行拆分。
my $path = "/bla/bla/bla/20160306";
my $date = (split(/\//,$path))[3];#ideally 3 is date position in array after split
print $date;
然而,我并没有看到预期的输出,而是看到了数字5被打印出来。
由于路径以模式/
本身开头,split返回一个列表,其中第一个元素为空字符串(在第一个/
左侧); 元素比原来多一个。因此,发布的代码错误计算了一个,并返回路径中倒数第二个元素(子目录),而不是日期。
如果日期始终是字符串中的最后一项,则可以选择最后一个元素。
my $date = (split '/', $path)[-1];
我在使用''
作为分隔符,以免需要转义/
。(然而,这可能会引起混淆,因为分隔符模式是一个正则表达式,而//
表达了这一点,而''
似乎只是引用一个字符串。)
这也可以用正则表达式来实现
my @parts = $path =~ m{([^/]+)}g;
这样就不会有初始空字符串了。或者,可以像上面那样从完整列表中挑选出最后一部分,使用 ($path =~ m{...}g)[-1]
,但如果您只需要最后一部分,则直接提取它即可。
my ($last_part) = $path =~ m{.*/(.*)};
.*
匹配字符串中的所有内容,直到下一个子模式(这里是/
)的最后一个实例,因此使我们到达路径的最后一部分,然后进行捕获。正则表达式匹配运算符仅在列表上下文中返回其匹配项,因此需要左括号。
为什么要解析路径?因为有专门用于此目的的库。
将路径拆分为其组成部分的一种工具是 File::Spec 的 splitdir
。
use File::Spec;
my @parts = File::Spec->splitdir($path);
/
开头,我们将再次获得第一个元素的空字符串(按设计,参见文档)。如果存在这种情况,则可以将其删除。shift @parts if $parts[0] eq '';
同样地,最后一个元素也可以像其他示例中一样获得。
split
会将字符串分解成所有找到的'/'周围的部分。(这里的所有示例都经过测试并且有效,请尝试一下。) - zdimsplit
中的模式由其他字符而非/
本身分隔,则我们不需要在模式中转义/
(正如我在回答中所解释的那样?)。 因此,split m{/}
很好,split m|/|
和split m#/#
也是如此。 使用引号是特别允许的(因此不需要m
),因此split'/'
或split"/"
也可以。 现在,如果想要使用通常的/.../
作为定界符,那么确实需要转义它,split /\//
。 这就是你的意思吗? - zdimsplit
函数的分隔符参数是一个正则表达式,因此需要按照语法规则进行处理。我在答案中添加了链接。除此之外,引号是特别允许的(在普通的正则表达式中,需要在前面加上 m
,即 $v =~ m"pattern"
)。 - zdimSimply 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:一个演示}}
。试试这个
使用前瞻来完成它。通过分割捕获/
。然后使用/
替换数据以去除斜杠。
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];
use Data::Dumper; print Dumper \@split;
- TLP