3

所以,我在另一篇文章中看到,要使用\\分隔符进行拆分,您需要在\\\\\\\\. 这对我来说真的没有意义,但是当我尝试使用拆分时\\\\,发生了这种情况:

my $string="a\\\\b\\\\c";
my @ra=split("\\\\",$string);

数组是:

a
<empty>    
b
<empty>
c

正如另一位海报所说,使用\\\\\\\\效果很好。为什么会这样?

另外,我很好奇并开始搞乱''vs""并得到了意想不到的结果。我以为我理解了区别是什么,但我想我没有,至少在以下情况下没有:

my $string="a\.\.b\.\.c";
my @ra=split("\.\.",$string);

数组是:

<empty>
<empty>
<empty>
c

然而,

my $string="a\.\.b\.\.c";
my @ra=split('\.\.',$string);

数组是:

a
b
c

提前致谢。

4

3 回答 3

4

哦,引用规则和正则表达式。

带有不同引号的反斜杠规则

  • q()相关方面,所有反斜杠都留在字符串中,除非它们转义字符串分隔符或另一个反斜杠:

    say '\a\\b\''; # »\a\b'«
    
  • qq()相关的情况下,所有不形成已知字符串转义序列的反斜杠都会被静默删除:

    say "\d\\b\"\."; # »d\b."«
    
  • 同上qr//和正则表达式文字,除了与双引号字符串相比有不同的转义。

如果使用字符串代替正则表达式,则在编译期间会执行该字符串的转义规则。但是,当它用作正则表达式时,会处理第二级转义,因此在最坏的情况下必须对反斜杠进行双重转义。正则表达式文字不会遇到这个问题;只有一层逃脱。

你的例子的解释

因此,"a\\\\b\\\\c";isa\\b\\c"\\\\"is\\匹配\为正则表达式。所以它在每个反斜杠上拆分,从而在双反斜杠之间产生零长度字段。

你的'\\\\\\\\'意思的另一个问题是\\\\哪个作为正则表达式匹配\\

"a\.\.b\.\.c"isa..b..c"\.\."is作为正..则表达式匹配两个非换行符。它首先匹配a.,然后.b,然后..。这会产生字符串片段"", "", "", "c"

字符串'\.\.'is \.\.,作为正则表达式,它按顺序匹配两个文字句点。

解决方案是在正则表达式到期的地方使用正则表达式。split将正则表达式作为第一个参数,例如split /foo/,在其他情况下,正则表达式引用qr/foo/很有用。这避免了令人费解的[1]双重转义。

[1]:对于“心灵弯曲”的小值,一旦你了解了规则。

于 2013-05-15T22:45:44.040 回答
3
  • 在单引号字符串文字中,

    • \后跟字符串分隔符('默认情况下)导致字符串分隔符。

      'That\'s fool\'s gold!'   -> That's fool's gold!
      q!That's fool's gold\!!   -> That's fool's gold!
      
    • \其次是\结果\

      'c:\\foo'                 -> c:\foo
      
    • \后跟其他任何内容都会导致这两个字符。

      'c:\foo'                  -> c:\foo
      
  • 在双引号字符串文字中,

    • \后跟非单词字符会导致该字符。

      "c:\\foo"                 -> c:\foo
      "Can't open \"foo\""      -> Can't open "foo"
      
    • \后面跟单词字符有特殊含义。

      "foo\n"                   -> foo{newline}
      
  • 在正则表达式文字中,

    • \后跟分隔符被替换导致分隔符。

      qr/\//                    -> /
      
    • \后跟其他任何内容都会导致这两个字符。

      qr/\\/                    -> \\
      qr/\_/                    -> \_
      qr/\$/                    -> \$
      qr/\n/                    -> \n
      
  • 应用正则表达式时,

    • \后跟非单词字符匹配该字符。

      /c:\\foo/                 -> Matches strings containing: c:\foo
      
    • \后面跟单词字符有特殊含义。

      /foo\z/                   -> Matches strings ending with: foo
      

查看您的案例:

 my $string="a\\\\b\\\\c";
 my @ra=split("\\\\",$string);

"\\\\"结果为字符串\\,因此您首先创建字符串a\\b\\c并传递\\split.

的第一个参数split用作正则表达式,正则表达式模式\\匹配单个\. 有 4\英寸a\\b\\c,所以它被分成 4+1 块。

如果您使用正则表达式文字而不是双引号字符串文字,则会减少混淆。

split(/\\/, $string);        # Passes pattern \\ to split. Matches singles
split("\\\\", $string);      # Passes pattern \\ to split. Matches singles
split(/\\\\/, $string);      # Passes pattern \\\\ to split. Matches doubles
split("\\\\\\\\", $string);  # Passes pattern \\\\ to split. Matches doubles

简而言之,不要使用split "..."


您的其他两种情况现在对您来说应该很明显了。

my $string="a\.\.b\.\.c";          # String a..b..c
my @ra=split("\.\.",$string);      # Pattern .., which matches any two chars.

my $string="a\.\.b\.\.c";          # String a..b..c
my @ra=split('\.\.',$string);      # Pattern \.\., which matches two periods.
于 2013-05-16T00:04:35.317 回答
0

使用 /\\\\/ 而不是 "\\\\" 拆分并避免所有后顾之忧,

例如

use Data::Dumper;

my $string= "a\\\\b\\\\c";

my @ra = split /\\\\/, $string;

print Dumper @ra;

将输出

$VAR1 = [
          'a',
          'b',
          'c'
        ];

/\\/ 将连续匹配两个 \

或者你可以很可爱,做

split /\\{2}/, $string
于 2013-05-16T00:20:17.867 回答