7

有人可以解释这种奇怪的行为:

我在字符串中有路径,我想为每个反斜杠拆分它

my $path = "D:\Folder\AnotherFolder\file.txt";

my @folders = split('\', $path);

在上述情况下,即使像这样转义反斜杠也不会起作用:

my @folders = split('\\', $path);

但在正则表达式的情况下,它将起作用:

my @folders = split( /\\/, $path);

为什么会这样?

4

4 回答 4

6

I think amon gave the best literal answer to your question in his comment:

more explicitly: strings and regexes have different rules for escaping. If a string is used in place of a regex, the string literals suffer from double escaping

Meaning that split '\\' uses a string and split /\\/ uses a regex.

As a practical answer, I wanted to add this:

Perhaps you should consider using a module suited for splitting paths. File::Spec is a core module in Perl 5. And also, you have to escape backslash in a double quoted string, which you have not done. You can also use single quotes, which looks a bit better in my opinion.

use strict;
use warnings;
use Data::Dumper;
use File::Spec;

my $path = 'D:\Folder\AnotherFolder\file.txt';  # note the single quotes
my @elements = File::Spec->splitdir($path);
print Dumper \@elements;

Output:

$VAR1 = [
          'D:',
          'Folder',
          'AnotherFolder',
          'file.txt'
        ];
于 2013-09-30T13:02:44.637 回答
2

当以and notsplit的形式使用时,字符串被转换为正则表达式。在您的情况下,将转换为,因为第一个反斜杠被视为转义字符。split STRINGsplit REGEXsplit '\\'split /\/

正确的做法是split '\\\\'将其翻译为split /\\/.

于 2013-09-30T14:56:22.137 回答
2

如果您通过运行查看文档:

perldoc -f split

您将看到split可以采用的三种形式的参数:

split /PATTERN/,EXPR,LIMIT
split /PATTERN/,EXPR
split /PATTERN/

这意味着即使您将split字符串作为第一个参数传递,也会将perl其强制转换为正则表达式。

如果我们查看在尝试执行以下操作时收到的警告re.pl

$ my $string_with_backslashes = "Hello\\there\\friend";
Hello\there\friend
$ my @arry = split('\\', $string_with_backslashes);
Compile error: Trailing \ in regex m/\/ at (eval 287) line 6.

我们首先看到,它'\\'被插入为反斜杠转义,然后是一个实际的反斜杠,其计算结果为单个反斜杠。

split然后放上我们给它的反斜杠,并将它强制转换为正则表达式,就像我们写的一样:

$ my @arry = split(/\/, $string_with_backslashes);

这不起作用,因为只有一个反斜杠被解释为只是在它之后转义正斜杠(没有终止/)以表明正则表达式已经结束。

于 2013-09-30T12:49:23.730 回答
2

提取路径元素的一种更简洁的方法是提取除路径分隔符之外的所有字符序列。

use strict;
use warnings;

my $path = 'D:\Folder\AnotherFolder\file.txt';
my @path = $path =~ m([^/\\]+)g;

print "$_\n" for @path;

输出

D:
Folder
AnotherFolder
file.txt
于 2013-09-30T13:07:01.447 回答