在Perl中根据定界符动态地改变键值。

问题描述 投票:0回答:1

我从一个CSV文件中读取数据,并根据Key-Value Pairs填充一个Hash,记录的第一列是Key,其余的记录是value。然而,对于某些文件,我需要将前两列作为Key,其余的记录为value。我根据以下内容写成了 if 循环,但我想知道是否有更好的方法?

use strict;
use warnings;

open my $fh, '<:encoding(utf8)', 'Sample.csv'
      or die "Couldn't open Sample.csv";
my %hash;     
my $KeyCols=2;
    while (<$fh>) {
        chomp;
        if ($KeyCols==1) {
        next unless /^(.*?),(.*)$/;
        $hash{$1} = $2;
        }
        elsif ($KeyCols==2) {
        next unless /^(.*?),(.*?),(.*)$/;
        $hash{$1.$2} = $3;
        }
    }
perl strawberry-perl
1个回答
3
投票

这里有一种方法允许任何数量的键列(不只是1或2),但它使用的是 split 而不是regex。

use warnings;
use strict;

my %hash;     
my $KeyCols = 2;
while (<DATA>) {
    chomp;
    my @cols = split /,/, $_, $KeyCols+1;
    next unless @cols > $KeyCols;
    my $v = pop @cols;
    my $k = join '', @cols;
    $hash{$k} = $v;
}

__DATA__
a,b,c,d,e,f
q,w,e,r,t,y

这是一个自成一体的代码示例。


一个重要的假设是,你的CSV文件中的数据本身不包含逗号。 你应该使用一个CSV解析器,如 Text::CSV 反正。


1
投票

也许最好在代码的第一行定义变量--否则你必须在代码中定义 跳跃 遍布整个代码。

您可以定义 检索词 基于你 $KeyCols 和处理代码将与以前一样。

use strict;
use warnings;
use feature 'say';

my $KeyCols = 2;
my $fname   = 'Sample.csv';

my %hash;
my $re;

if( $KeyCols == 2 ) {
    $re = qr/^(.*?,.*?),(.*)$/ 
} else {
    $re = qr/^(.*?),(.*)$/;
}

open my $fh, '<:encoding(utf8)', $fname
      or die "Couldn't open $fname";

while (<$fh>) {
    chomp;
    next unless /$re/;
    $hash{$1} = $2;
}

close $fh;
© www.soinside.com 2019 - 2024. All rights reserved.