2013-07-02 88 views
1

因此,我有一个列出每个密钥(每行一个)的文件keys.txt,例如从文件中的密钥列表中查找文件中缺失的密钥

VIEW_ACCOUNT_NAME_LABEL 
VIEW_ACCOUNT_NAME_DESCR 
VIEW_ACCOUNT_STREET_LABEL 
VIEW_ACCOUNT_CITY_SUBURB_LABEL 
VIEW_ACCOUNT_ZIP_POSTCODE_LABEL 
VIEW_ACCOUNT_COUNTRY_LABEL 

以及各种配套语言文件,对于该键提供值,如en-GB.view.acccount.ini具有每行一个条目,像这样:

VIEW_ACCOUNT_NAME_LABEL="Name:" 
VIEW_ACCOUNT_NAME_DESCR="Name of the account holder." 
VIEW_ACCOUNT_STREET_LABEL="Street:" 
VIEW_ACCOUNT_CITY_SUBURB_LABEL="City/Suburb:" 
VIEW_ACCOUNT_ZIP="Zip Code" 
VIEW_ACCOUNT_COUNTRY_LABEL="Country" 

注:有许多关键和语言文件,实际文件有更多的条目 - 通常超过1000种语言。

我需要能够找到

  1. 哪些键的语言文件丢失(例如,VIEW_ACCOUNT_ZIP_POSTCODE_LABEL
  2. 哪些键在语言文件,但不能在密钥文件(通常是过时的密钥如VIEW_ACCOUNT_ZIP

因为我使用grep-v反转匹配选项尝试的第一个要求,但结果不出我所料:

cppl ~ grep -v --file=keys.txt en-GB.view.acccount.ini 
VIEW_ACCOUNT_NAME_LABEL="Name:" 
VIEW_ACCOUNT_NAME_DESCR="Name of the account holder." 
VIEW_ACCOUNT_STREET_LABEL="Street:" 
VIEW_ACCOUNT_CITY_SUBURB_LABEL="City/Suburb:" 
VIEW_ACCOUNT_ZIP="Zip Code" 
cppl ~ 

回答

0

您可以使用标准的UNIX工具joinuniq做到这一点。这是一种方法。

我假设你的密钥文件在下面的例子中被命名为file1

生成只包含键的文件,而不包含值。

sed 's/=.*//' en-GB.view.acccount.ini > file2

你现在有file1和仅包含键file2。在这个例子中:

$ cat file1 
A 
B 
C 
D 

$ cat file2 
C 
D 
E 

您现在可以使用的joinsortuniq组合,让您所需的输出。

# Keys which are common to both files. 
$ join file1 file2 | cat - file1 | sort | uniq -d 
C 
D 

# Keys in file1 but not in file2 
$ join file1 file2 | cat - file1 | sort | uniq -u 
A 
B 

# Keys in file2 but not in file1 
$ join file1 file2 | cat - file2 | sort | uniq -u 
E 
4

使用comm

要找出哪些键的语言文件丢失:

$ comm -23 <(sort keys.txt) <(cut -d= -f1 en-GB.view.acccount.ini | sort) 
VIEW_ACCOUNT_ZIP_POSTCODE_LABEL 

要了解哪些键在语言文件,但不能在密钥文件:

$ comm -13 <(sort keys.txt) <(cut -d= -f1 en-GB.view.acccount.ini | sort) 
VIEW_ACCOUNT_ZIP 
+0

我喜欢它。使用'comm'似乎比我想到的方法更适合这个确切的任务。 –

+0

感谢您的回答,但我没有得到相同的结果。如果我正确理解这一点,那么这两个文件都会被排序然后传回给'comm'。语言文件通过cut传递,以便在排序前返回键,所以'comm'有效地比较了两组键。这一切都非常有意义,除了我得到这个: 'cppl〜comm -23 <(sort keys.txt)<(cut -d = -f1 zh-GB.view.acccount.ini | sort) VIEW_ACCOUNT_CITY_SUBURB_LABEL VIEW_ACCOUNT_NAME_DESCR VIEW_ACCOUNT_NAME_LABEL VIEW_ACCOUNT_STREET_LABEL VIEW_ACCOUNT_ZIP_POSTCODE_LABEL' – Craig

+0

你已经在钥匙任何尾随空格的文件?如果是的话,你将不得不删除它们。尝试'comm -23 <(sed's/* // g'keys.txt | sort)<(cut -d = -f1 en-GB.view.acccount.ini | sort)' – dogbane

0

您能够使用perl的呢?如果是这样,perl使这超级简单。这是一个我鞭打的快速而肮脏的脚本。修改以适应您的口味。

#!/usr/bin/perl -w 

# usage: validate keys.txt file1.ini [file2.ini [file3.ini [...]]] 

open my $keys_file, "<", $ARGV[0] or die "cannot open $ARGV[0] for reading"; 

my %keys = (map { chomp; s/\s//g; $_ => 0 } <$keys_file>); 

close $keys_file; 

sub validate_file 
{ 
    my $filename = shift @_; 
    my (@missing, @unexpected, @repeated); 
    my %seen = %keys; 

    open my $f, "<", $filename or die "cannot open $filename for reading"; 

    foreach my $line (<$f>) 
    { 
     chomp $line; 

     if ($line =~ /\s*([^=]+)="[^"]*"/) 
     { 
      if (!defined $seen{$1}) 
      { 
       push @unexpected, $1; 
       $seen{$1} = 0; 
      } 
      $seen{$1}++; 
     } 
    } 

    @missing = grep { $seen{$_} == 0 } sort keys %keys; 
    @repeated = grep { $seen{$_} > 1 } sort keys %keys; 

    return \@missing, \@unexpected, \@repeated; 
} 


shift @ARGV; 

foreach my $file (@ARGV) 
{ 
    my ($missing, $unexpected, $repeated) = validate_file($file); 

    print "\nFile $file:\n"; 
    print "Missing keys:\n", join("\n", @$missing), "\n"; 
    print "Unexpected keys:\n", join("\n", @$unexpected), "\n"; 
    print "Repeated keys:\n", join("\n", @$repeated), "\n"; 
}