当令牌之间没有值时,Perl拆分函数会返回什么?

时间:2010-10-26 20:59:46

标签: perl split

我正在尝试使用split函数拆分字符串,但令牌之间并不总是有值。

例如:ABC,123 ,,,,,, XYZ

我不想跳过多个令牌。这些值位于字符串中的特定位置。但是,当我进行拆分,然后尝试单步执行生成的数组时,我会收到“使用未初始化的值”警告。

我尝试使用$splitvalues[x] eq ""比较值,我尝试使用defined($splitvalues[x]),但我不能在我的生活中弄清楚如何识别分割函数放入的内容当令牌之间没有值时,我的数组。

这是我的代码片段(现在有更多脆弱的好处):

my @matrixDetail = ();

#some other processing happens here that is based on matching data from the 
#@oldDetail array with the first field of the @matrixLine array. If it does
#match, then I do the split
if($IHaveAMatch)
{
    @matrixDetail = split(',', $matrixLine[1]);
}
else
{
    @matrixDetail = ('','','','','','','');
}

my $newDetailString =
  (($matrixDetail[0] eq '') ? $oldDetail[0] : $matrixDetail[0])
. (($matrixDetail[1] eq '') ? $oldDetail[1] : $matrixDetail[1]) 
    .
    .
    .
. (($matrixDetail[6] eq '') ? $oldDetail[6] : $matrixDetail[6]);

因为这只是片段,我还剩下其他一些逻辑,但if语句位于一个技术上返回@matrixDetail数组的子语句中。如果我在我的矩阵中找不到匹配并且手动将数组设置为等于空字符串数组,那么我没有得到任何警告。只有在拆分填充@matrixDetail时才会这样。

另外,我应该提一下,我已经编写了将近15年的代码,但直到最近我才需要使用Perl。我的剧本中的逻辑是合理的(或至少,它有效),我只是在唠叨清理我的警告并试图找出这个小细微差别。

4 个答案:

答案 0 :(得分:4)

#!perl

use warnings;
use strict;
use Data::Dumper;

my $str = "ABC,123,,,,,,XYZ";
my @elems = split ',', $str;
print Dumper \@elems;

这给出了:

$VAR1 = [
          'ABC',
          '123',
          '',
          '',
          '',
          '',
          '',
          'XYZ'
        ];

它放入一个空字符串。

编辑请注意,documentation for split()表示“默认情况下会保留空的前导字段,并删除空的尾随字段”。因此,如果您的字符串是ABC,123,,,,,,XYZ,,,,,那么您返回的列表将与上面的示例相同,但如果您的字符串是,,,,ABC,123,那么您将在元素0,1中有一个包含三个空字符串的列表,和2(除了'ABC''123')。

编辑2 :尝试转出@matrixDetail@oldDetail数组。其中一个可能不是你认为的长度。在尝试使用它们之前,您还可以考虑检查这两个列表中的元素数量,以确保您拥有与预期一样多的元素。

答案 1 :(得分:1)

我建议使用CPAN中的Text::CSV。它是一个现成的解决方案,已经涵盖了解析CSV格式文件的所有奇怪边缘情况。

答案 2 :(得分:0)

在它们之间没有任何区别,在分割时给出空字符串。在布尔上下文中,空字符串评估为false

如果你知道你的“详细信息”输入永远不会包含“0”(或其他评估为false的标量),这应该有效:

my @matrixDetail = split(',', $matrixLine[1]);
die if @matrixDetail > @oldDetail;

my $newDetailString = "";
for my $i (0..$#oldDetail) {
    $newDetailString .= $matrixDetail[$i] || $oldDetail[$i]; # thanks canSpice
}
say $newDetailString;

(除了空字符串和零之外可能还有其他标量评估为false但我无法将它们命名为我的头顶。)

TMTOWTDI:

$matrixDetail[$_] ||= $oldDetail[$_] for 0..$#oldDetail;
my $newDetailString = join("", @matrixDetail);

编辑:for循环现在从0变为$#oldDetail而不是$#matrixDetail,因为尾随“,,,”不会被分割返回。

edit2:如果你不能确定实际输入不会被评估为false,你可以随时测试分割元素的长度。这绝对是更安全的,尽管可能不那么优雅^ _ ^

答案 3 :(得分:0)

中间的空白字段将是''。除非您指定第三个参数足够大(或-1表示所有),否则将省略末尾的空字段。