tab - perl分裂有趣的行為




unix perl split (3)

有人可以解釋這個奇怪的行為:

我有一個字符串的路徑,我想分裂為每個反斜杠

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

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

在上面的情況下,即使像這樣轉義反斜杠也不行:

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

但在正則表達式的情況下,它將工作:

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

為什麼是這樣?


如果您通過運行查看文檔:

perldoc -f split

你會看到split可以採取的三種形式的論據:

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

這意味著,即使當你傳遞一個字符串作為第一個參數, 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);

這是行不通的,因為只有一個反斜杠被解釋為簡單地在正斜杠後面(而不是終止/ )顯示正則表達式已經結束。


我認為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'
        ];

當以split STRING的形式使用split STRING而不是split REGEX ,字符串被轉換成正則表達式。 在你的情況下, split '\\'將被轉換為split /\/因為第一個反斜杠被認為是一個轉義字符。

正確的做法是split '\\\\' ,將其轉換為split /\\/





split