2013-09-30 32 views
6

有人可以解释这种怪异的行为:perl的分裂有趣的行为

我HAVA路径字符串,我想在的情况下把它分解为每个反斜杠

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

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

上面也不会不工作即使逃脱这样的反斜杠:

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

,但在正则表达式的情况下,将工作:

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

为什么如此?

+2

你在路径中的逃跑是错误的。在双引号字符串中,“\ Folder”被解释为转义序列“\ F”。 – TLP

+4

对split分隔符模式使用引号是不好的做法,因为它不能正确表达语义并导致双重编译。总是使用斜线,除非你想传递一个空格字符串来调用默认行为,当''''是正确的选择。 – Borodin

+0

@TLP是的,我知道,我通常只为路径放置单引号。谢谢 –

回答

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); 

不工作,因为只有这被解释为只是逃避单反斜线它后面的正斜杠(没有终止/)表明正则表达式已经结束。

+0

实际上,如果它是逃避斜线,你会得到错误“搜索模式没有终止”,这意味着操作员被打破。这是别的。 – TLP

+3

更明确:字符串和正则表达式有不同的转义规则。如果使用字符串代替正则表达式,则字符串文字会遭受双重转义。 – amon

+0

@ user1436026我确实读过perldoc,但不太明白innerworks,不知道你放入的任何东西仍然会变成正则表达式 –

5

我觉得amon了在他的评论最好的字面回答你的问题:

更明确:字符串和正则表达式有逃避不同的规则。如果字符串代替正则表达式中使用的字符串常量,从双重逸出

意思就是说split '\\'使用字符串和split /\\/使用正则表达式受到影响。

作为一个实际的答案,我想补充一点:

也许你应该考虑使用适合分割路径的模块。 File::Spec是Perl 5中的一个核心模块。而且,您还必须在双引号字符串中转义反斜杠,而您还没有这样做。您也可以使用单引号,在我看来这看起来好一点。

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; 

输出:

$VAR1 = [ 
      'D:', 
      'Folder', 
      'AnotherFolder', 
      'file.txt' 
     ]; 
+0

感谢File :: Spec –

+0

@AndreiDoanca用于分割路径的正确工具,并且它具有可移植性和可靠性。我不确定你想通过分割路径来做什么,但它看起来像一个XY问题。 – TLP

+0

其实它不是一个XY-问题只是我的好奇心:) –

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 
2

split当在split STRING形式使用,而不是split REGEX,该字符串被转换为正则表达式。在你的情况下,split '\\'将被转换为split /\/,因为第一个反斜杠被认为是一个转义字符。

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

+0

非常感谢解释,真的很好的信息:)我现在明白,看到它的作品:) –