当我遇到一个让我困惑的引语时,我跟着这个tutorial关于如何分割字符串。
有关上下文的文字
正常使用时,split在列表上下文中使用。它也可能是 在标量上下文中使用,尽管它在标量上下文中使用 弃用。在标量上下文中,split返回字段数 找到了,并拆分成@_数组。很容易理解为什么会这样 不可取,因此,为什么在标量上下文中使用split是 不高兴。
我有以下与我合作过的脚本:
#!/usr/bin/perl
use strict;
use warnings;
use v5.24;
doWork();
sub doWork {
my $str = "This,is,data";
my @splitData = split(/,/, $str);
say $splitData[1];
return;
}
我不完全明白如何在列表中使用拆分。
根据我的理解,在split
变量上使用$str
函数是不受欢迎的?那么我怎么会用逗号分隔字符串作为分隔符呢?
答案 0 :(得分:2)
该段所记录的皱眉行为至少被推迟至5.8.8(11年前),并于5.12(7年前)从Perl中删除。
段落文件
my $n = split(...);
相当于
my $n = do { @_ = split(...); @_ }; # <5.12
@_
的分配是意外的。这种行为称为“远距离令人惊讶的行为”,它可能导致代码故障。因此,在5.12之前,在标量上下文中使用split
是不受欢迎的。但是,从5.12开始,
my $n = split(...);
相当于
my $n = do { my @anon = split(...); @anon }; # ≥5.12
已删除令人惊讶的行为,因为您引用的段落中所述的原因,在标量上下文中使用split
不再感到不满。
它应该仍然可以避免,不仅仅是为了向后兼容,而是因为有更好的方法来计算子串的数量。我会使用以下内容:
my $n = 1 + tr/,//; # Faster than: my $n = split(/,/, $_, -1);
您在列表上下文中使用split
,因此无论您使用何种版本的Perl,它都不会行使皱眉的行为。换句话说,您的使用情况很好。
除非你试图处理CSV数据,否则没关系。在这种情况下,您应该使用Text::CSV_XS。
use Text::CSV_XS qw( );
my $csv = Text::CSV_XS->new({ auto_diag => 2, binary => 1 });
while (my $row = $csv->getline($fh)) { ... } # Parsing CSV
for (...) { $csv->say($fh, $row); } # Generating CSV
答案 1 :(得分:1)
在标量上下文中调用split
并不是很有用。它有效地返回了分隔符的数量加上一个,并且有更好的方法可以做到这一点。
例如,
my $str = "This,is,data";
my $splitData = split(/,/, $str);
say $splitData;
将打印3
,因为它会在拆分后计算子字符串。
split
过去也会返回@_
中的分割部分,但这种皱眉的行为被删除了,因为它很意外。
将它用作数组是完美的。
my $str = "This,is,data";
以上行是单个字符串。
my @splitData = split(/,/, $str);
您现在将$str
拆分为数组或值列表。所以你现在正在和@splitData坐在一起,这实际上是:
"This" "is" "string"
因此,您可以全部使用它们,say @splitData
或将它们中的每一个用作我们从未使用的标量@splitData[1]
,因为将它写为$splitData[1]
教程说得很好。在字符串上使用split来创建子字符串列表。
然后,您可以显然自动在循环中分配每个列表值,而无需打印每个列表值。
my $str = "This,is,data";
my @splitData = split(/,/, $str);
foreach $value(@splitData) {
say "$value\n"
}
这基本上会将$splitData[0], $splitData[1]
等重新分配给$value
作为标量。