TEST.TXT
name a b c d
car 1 2 0 7
tram 7 8 9 5
bus_db 1 6 3 8
cari
busi_db
OUT.txt
name a b c d
car 1 2 0 7
tram 7 8 9 5
bus_db 1 6 3 8
cari 1 2 0 7
busi_db 1 6 3 8
我有一个文件,如TEST.txt所示,其中几个键没有值。我想匹配没有值的键,并匹配匹配的键的相同值。示例输出如下所示。
编辑:我已经尝试了一个更长的过程来分离带有和不带有不同文件值的键,然后将这些文件与额外的“i”进行比较并附加值。我没有使用此过程获得所需的输出
答案 0 :(得分:1)
这个程序似乎可以满足您的需求。它期望源数据文件作为命令行上的参数
use strict;
use warnings;
<>;
my %data;
my @keys;
while (<>) {
my ($key, @values) = split;
if (@values) {
$data{$key} = \@values;
push @keys, $key;
}
else {
(my $newkey = $key) =~ s/i(?![a-z])//i;
my $values = $data{$newkey};
$data{$key} = [ @$values ];
push @keys, $key;
}
}
my $format = "%-7s%3s%3s%3s%3s\n";
printf $format, qw/ name a b c d /;
for my $key (@keys) {
printf $format, $key, @{ $data{$key} };
}
<强>输出强>
name a b c d
car 1 2 0 7
tram 7 8 9 5
bus_db 1 6 3 8
cari 1 2 0 7
busi_db 1 6 3 8
答案 1 :(得分:0)
这是一个解决方案。这假设空键全部以“i”或“i_db”结尾,并且必须删除i才能获得填充的密钥。如果不是这样,则必须更改行$other_key =~ s/i(?=(_db)?$)//g;
以匹配您要查找的内容。另外,我已经将文件I / O留给你了。
use strict; use warnings;
my $header = <DATA>;
#throw away the first field name, as it will be used as the hash key
my (undef,@fields) = (split /\s+/, $header);
my %hash;
#read in the file.
while (<DATA>)
{
my @row = split /\s+/;
for (0..$#fields)
{
$hash{$row[0]}{$fields[$_]} = $row[$_+1];
}
}
#find cases that don't have data and fill them in.
foreach my $line (keys %hash)
{
foreach (keys %{$hash{$line}})
{
unless (defined $hash{$line}{$_})
{
my $other_key = $line;
#Uses a lookahead assertion to match but not delete "_db"
$other_key =~ s/i(?=(_db)?$)//g;
if (defined $hash{$other_key}{$_})
{
$hash{$line}{$_} = $hash{$other_key}{$_}
}
}
}
}
#Print the output.
print $header;
foreach (keys %hash)
{
#Uses a hash slice to get all of the values at once.
print join (" ",$_, @{$hash{$_}}{@fields})."\n";
}
__END__
name a b c d
car 1 2 0 7
tram 7 8 9 5
bus_db 1 6 3 8
cari
busi_db
答案 2 :(得分:0)
让我们首先将数据导入Perl。您将打开该文件,并将其读取到第一个空格上的哈希分割中。我不介意将a
,b
,c
或d
拆分为单独的数据,因为它对程序没有任何影响:
use strict;
use warnings;
use autodie;
open INPUT, "<", "TEST.txt";
my %array;
while my $line (<INPUT>) {
chomp $line;
my ($key, $data) = split /\s+/, $line, 2;
$array{$key} = $value;
}
这将给我们以下内容:
$array{car} = "1 2 0 7";
$array{tram} = "7 8 9 5";
$array{bus_db} = "1 6 3 8";
$array{cari} = "";
$array{busi_db} = "";
现在,您 没有 的内容解释了:您如何知道空数组成员是否匹配非空数组成员。我如何知道cari
匹配 car
和busi_db
匹配 bus_db
?是i
附加到结尾,但在可能的db
后缀之前?他们应该知道他们的其他事情吗?
一旦弄明白,让它们匹配非常简单:
$array{busi_db} = $array{bus_db};
然后,将它们打印出来就很简单了。
# Go through array and make "null" members match
while my $key (sort keys %array) {
if (not $array{$key}) { #Ah! a null array member!
$matching_key = find_matching_key($key);
$array{$key} = $array{$matching_key};
}
}
# Print them out
while my $key (sort keys %array) {
print "$key = $array{$key}\n";
}
sub find_matching_key {
# Here be dragons....
}
问题是find_matching_key
子程序。你弄清楚是什么让两个单独的键匹配,并填写详细信息。
顺便说一句,根据您的示例数据,null成员位于非null成员之后。如果这始终是真实条件,则无需将读取循环与 merge 循环分开。不幸的是,你没有说这是否属实。
也没有,你是否指定我是否必须以与读入时相同的顺序打印数组。我可以保留一个键列表,并保持它们的顺序。我没有,因为它会使逻辑复杂化,而你没有指定它。
请注意您的问题排名较低,以及人们将其标记为关闭的事实。这是因为你基本上说:“我有这个问题,为我解决它”。您也没有提供足够的解决方案细节。正如我所说,你谈到了匹配密钥,但没有说明你的意思。