2012-08-17 166 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