在 Perl 中根据定界符动态更改键值

Dynamically Change the Key Value based on Delimiter in Perl

我正在读取 CSV 文件并根据键值对填充哈希。 记录的第一列是键,记录的其余部分是值。但是,对于某些文件,我需要将前 2 列作为键,其余记录是值。我已经通过检查关键列的数量基于 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{} = ;
        }
        elsif ($KeyCols==2) {
        next unless /^(.*?),(.*?),(.*)$/;
        $hash{.} = ;
        }
    }

这是一种允许任意数量的键列(不仅仅是 1 或 2)的方法,但它使用 split 而不是正则表达式:

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

也许最好在代码的第一行定义变量——否则你必须跳过整个代码。

您可以根据您的$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{} = ;
}

close $fh;