2012-08-17 144 views
-3

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其中有几个键那没有价值。我想匹配不具有值的键,并将相同的键值相同。示例输出如图所示。

编辑:我已经尝试了一个更长的过程,以在不同的文件中分别使用和不使用值的键,然后将这些文件与额外的“我”一起进行比较并追加值。我没有得到所需的输出使用这个程序

+3

[你有什么尝试?](http://whathaveyoutried.com) – Leri 2012-08-17 09:22:34

+1

在第一个“_”之前总会有“i”,如果没有“_”?可以用文字解释你的搜索模式吗? – tuxtimo 2012-08-17 09:32:49

+0

@ tuxtimo:是的,他们将永远是“我”与没有价值的钥匙附加。所以我想要随着价值一起出现的钥匙一起搜索我。 – unkaitha 2012-08-17 09:37:48

回答

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 
+0

它适用于我..很好,谢谢 – unkaitha 2012-08-20 01:11:14

+0

是他们的一行代码,可以添加到上面的代码将删除没有匹配键的行?例如从上面的输出“电车”? – unkaitha 2012-08-20 03:01:45

+0

不,这是一个完全不同的问题与不同的解决方案 – Borodin 2012-08-22 00:20:20

0

这是一个解决方案。这假定空键全部以“i”或“i_db”结尾,并且我必须被移除以获得填充密钥。如果不是这样,那么行$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 
0

让我们首先将数据进入的Perl。您将打开文件,并将其读入第一个空格的散列分割。我不在乎abc,或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匹配carbusi_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子程序。你找出两个单独的键匹配的内容,并填写详细信息。

顺便说一下,根据您的示例数据,空成员来到非空元素之后。如果这总是一个真实的条件,则不需要将读取循环与合并循环分开。不幸的是,你没有说这是否是真的。

也没有,你是否指定我是否必须按照读入的顺序打印数组。我可以保存一个键列表,并保持它们的顺序。我没有,因为它会使逻辑复杂化,而你没有指定它。


请注意您的问题的排名较低,以及人们将其标记为关闭的事实。这是因为你基本上说:“我有这个问题,为我解决”。您也没有提供足够的解决方案细节。正如我所说,你谈到匹配键,但没有具体说明你的意思。

+0

对于已发布的不完整问题,我感到非常抱歉,我将为我的进一步交谈记住一切事宜。并感谢您的详细解释 – unkaitha 2012-08-20 01:10:32