在 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;
我正在读取 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;