【问题标题】:How is the split function in perl supposed to work?perl 中的 split 函数应该如何工作?
【发布时间】:2013-12-03 10:29:44
【问题描述】:

我今天在使用拆分功能时遇到了一些困难,并阅读了perlfunc 看看我是否解释错了。我试图在 '.' 上拆分一个字符串,根据 perlfunc 应该因此得到支持:

my $string = "hello.world";
my ($hello, $world) = split(".", $string);

my $string = "hello.world";
my ($hello, $world) = split(/\./, $string);

但是,测试第一个导致空变量,所以我将测试扩展到以下内容:

#!/usr/bin/perl

use strict;
use warnings;

my $time_of_test = "13.11.19.11.45.07";
print "TOD: $time_of_test\n";
my ($year, $month, $day, $hr, $min, $sec) = split(/\./, $time_of_test);
print "Test 1 -- Year: $year month: $month day: $day hour: $hr min: $min sec: $sec\n";
($year, $month, $day, $hr, $min, $sec) = split(".", $time_of_test);
print "Test 2 -- Year: $year month: $month day: $day hour: $hr min: $min sec: $sec\n";
($year, $month, $day, $hr, $min, $sec) = split('.', $time_of_test);
print "Test 3 -- Year: $year month: $month day: $day hour: $hr min: $min sec: $sec\n";
($year, $month, $day, $hr, $min, $sec) = split("\.", $time_of_test);
print "Test 4 -- Year: $year month: $month day: $day hour: $hr min: $min sec: $sec\n";
($year, $month, $day, $hr, $min, $sec) = split('\.', $time_of_test);
print "Test 5 -- Year: $year month: $month day: $day hour: $hr min: $min sec: $sec\n";

这是输出:

> ./test.pl  
TOD: 13.11.19.11.45.07
Test 1 -- Year: 13 month: 11 day: 19 hour: 11 min: 45 sec: 07
Test 2 -- Year:  month:  day:  hour:  min:  sec: 
Test 3 -- Year:  month:  day:  hour:  min:  sec: 
Test 4 -- Year:  month:  day:  hour:  min:  sec: 
Test 5 -- Year: 13 month: 11 day: 19 hour: 11 min: 45 sec: 07

这是否按预期工作?如果是这样,我是如何误解 perlfunc 文档的?

【问题讨论】:

  • +1 这证实了我的怀疑,即 split 总是将第一个参数插入为正则表达式。
  • 如有疑问,请检查 perldoc => perldoc.perl.org/functions/split.html
  • 如果您没有让 Perl 抱怨 my $string = hello.world; 中的裸词,那么您就没有使用 use strict;use warnings;,这是……粗心?危险的?傻吗?
  • @JonathanLeffler - 你是对的,这对我来说是粗心的。我打算将这些信息设为伪代码。我测试的真实代码是从 she-bang 行开始的大块代码。很抱歉造成混乱。
  • 我已更新问题以更正裸词。

标签: regex perl split


【解决方案1】:

split 函数的第一个参数是正则表达式。 在正则表达式 '.'意思是“任何字符”。如果要在点处拆分,请使用 /\./ 转义 '.'

【讨论】:

  • 不管如何调用,它总是一个正则表达式吗?那样的话,我的意思是不会'\。和 ”\。”是同一个正则表达式吗?或者,是“\”。内插为字符串 \。在正则表达式中?
  • 是的!第一个参数是一个正则表达式。另请注意,字符串和正则表达式在 perl 中是不同的。与 java 或 C# 不同,perl 正则表达式是一流的文字。
  • @Bts,它总是一个正则表达式。 '\.' 产生字符串\."\." 产生字符串.,所以它们不一样。
【解决方案2】:

字符串文字'\n' 产生字符串\n。字符串文字'.' 产生字符串.。该字符串应为正则表达式。正则表达式中的. 匹配除换行符以外的任何字符。正则表达式\. 将匹配一个句点,并且该字符串可以从字符串文字'\.''\\.' 创建。不过,如果您使用/\./,则转义大多数模式的误导性更小,也更简单。

【讨论】:

    【解决方案3】:

    如果你想使用字符串分割.,你必须转义两次:

    my $string = 'hello.world';
    my ($hello, $world) = split('\\.', $string);
    print "$hello\n";
    

    输出“hello”。

    如果你只传入'\.',那么在拆分函数中这将只是一个通配符'.'。您需要两个反斜杠,以便将其作为 '\.' 传递给 split 函数。

    【讨论】:

    • 因为单引号将反斜杠视为文字,除非加倍或在字符串分隔符 '\.' 之前事实上确实有效(尽管“\。”没有)。但为了向读者展示它实际上是一个正则表达式,最好只使用 /\./
    【解决方案4】:

    split 的第一个参数是一个正则表达式。你不应该在这里使用字符串(" " 的特殊情况除外),因为它会误导实际行为。

    使用"."'.' 拆分时没有结果的原因是它将它们解释为正则表达式(拆分everything)。

    使用/\./'\.' 可以获得预期结果,因为点在正则表达式中被正确转义。

    您没有得到"\." 的任何结果,因为它首先被双引号字符串视为转义序列,然后被split 视为正则表达式。到 split 调用时,它与 "." 相同。

    【讨论】:

    • "" 不是特殊情况,它的处理方式与 //
    • @ysth 你是对的,就功能而言,这不是一个特殊情况,但在可读性方面更多。我认为这是可以接受使用字符串而不是正则表达式的情况。
    猜你喜欢
    • 2017-01-19
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    相关资源
    最近更新 更多