【问题标题】:Not able to divide each row of a csv file in the form of array using perl无法使用 perl 以数组形式划分 csv 文件的每一行
【发布时间】:2019-08-01 17:06:16
【问题描述】:

我遇到了解析 csv 文件的问题。 CSV 文件看起来像-

CPU Name,DISABLE,Memory,Encoding,Extra Encoding
,b,d,,
String1,YES,1TB,Enabled,Enabled
String2,NO,1TB,Enabled,Enabled
String3,YES,1TB,Enabled,Enabled

我想在两个不同的数组中捕获前两行。我用来做的代码是-

my $row_no =0;
while(my $row=<$fi>){
chomp($row);
$row=~ s/\A\s+//g;
$row=~s/\R//g;
#say $row;
if($row_no==0)
{
    #say $row;
    my @name_initial = split(',',$row);
    say length(@name_initial);
    say @name_initial;
}
elsif($row_no==1)
{
    #say $row;
    @data_type_initial =split(',',$row);
    say length(@data_type_initial);
    say @data_type_initial;
}
$row_no++;
}

现在我从文件中最上面的两行(分别为@name_initial 和@data_type_initial)形成了两个数组。当我打印这些数组时,我可以看到所有 5 个值,但是当我打印数组的长度时,它显示的长度为每个数组为 1。当我使用数组的索引打印元素时,我发现每个元素都在适当的位置,那么为什么它显示长度为 1。由 csv 文件的第二行形成的第二个数组也打印为“bd”。所有空值都消失了,尽管它包含两个值“b”和“d”。它的长度打印为 1。

我想用所有 null 和 non_NULL 值转换数组中的 csv 文件行,以便我可以迭代数组元素并可以根据 null 和非 null 值给出条件。我该怎么做???

【问题讨论】:

    标签: arrays perl csv


    【解决方案1】:

    看看perldoc length。它是这样说的:

    长度表达式

    长度

    返回 字符 的值的长度 快递。如果省略 EXPR,则返回 $_ 的长度。如果 EXPR 是 未定义,返回undef

    此函数不能用于整个数组或散列来找出 这些有多少元素。为此,请分别使用scalar @arrayscalar keys %hash

    像所有 Perl 字符操作一样,长度通常处理逻辑 字符,而不是物理字节。一个字符串编码为多少字节 UTF-8 会占用,使用 length(Encode::encode('UTF-8', EXPR))(你会 必须先use Encode)。请参阅编码和 perlunicode。

    特别是“此函数不能用于整个数组或散列以找出它们有多少元素。为此,请分别使用scalar @arrayscalar keys %hash”。

    所以你在这里使用了错误的方法。你需要say scalar(@array),而不是say length(@array)

    解释你得到的结果。 length() 期望得到一个标量值(一个字符串)来测量。因此,它将您的数组视为标量(有效地添加对scalar() 的不可见调用)并返回数组中的元素数(即“5”)和length() 然后告诉您该字符串中的元素数- 即 1。

    还值得指出的是,您不需要跟踪自己的 $row_no 变量。 Perl 有一个名为$. 的内置变量,其中包含当前记录号。

    使用这些知识(并添加少量空格)给我们带来了这样的结果:

    while (my $row = <$fi>) {
      chomp($row);
    
      $row =~ s/\A\s+//g;
      $row =~s/\R//g;
    
      #say $row;
    
      if ($. == 0) {
        #say $row;
        my @name_initial = split(/,/, $row);
        say scalar(@name_initial);
        say @name_initial;
      } elsif ($. == 1) {
        #say $row;
        @data_type_initial = split(/,/, $row);
        say scalar(@data_type_initial);
        say @data_type_initial;
      }
    }
    

    更新:你在这个问题的最后偷偷问了几个额外的问题。我建议你单独提出这些。

    【讨论】:

    • 非常感谢您的回复。当我使用标量打印时,第二个数组给出的计数为 3。它应该给出 5(包括 NULL 和 non_NULL 值)为什么它给出的计数为 3。你有什么想法吗?-@Dave Cross
    • @rikki:是的,我有一个想法。如果您阅读documentation for split(),您会发现它实际上需要三个参数,而第三个(限制)是可选的,实际上很少使用。如果省略限制,则从函数返回的列表中删除尾随的空字段。您可以明确地将其限制为 5,但更灵活的解决方案是使用 -1(因为 split() 会拆分为最大数量的字段并且不会删除空字段)。
    • @rikki:有很多非常好的 Perl 文档。但是如果人们不阅读它,那就有点浪费了:-)
    猜你喜欢
    • 2018-08-11
    • 2021-07-15
    • 2012-09-16
    • 2013-03-12
    • 2022-01-10
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多