2

我编写了一个 Perl 脚本,它有两个输入文件:

  1. 第一个文件在每一行都有短语,然后是括号之间的值。这里有一个例子:

    hello all (0.5)
    hi all (0.63)
    good bye all (0.09)
    
  2. 第二个文件有一个规则列表。例如:

    hello all -> salut (0.5)
    hello all -> salut à tous (0.5)
    hi all -> salut (0.63)
    good bye all -> au revoir (0.09)
    good bye -> au revoir  (0.09)
    

hello all脚本必须读取第二个文件,并为每一行提取箭头之前的短语(例如,第一行:

如果存在,则将整行写入hello all -> salut (0.5)输出。所以在这个例子中,输出文件应该是:

hello all -> salut (0.5)
hello all -> salut à tous (0.5)
hi all -> > salut (0.63)
good bye all -> au revoir (0.09)

我的想法是将第一个文件的所有内容放入哈希表中。为此,我的脚本:

#!/usr/bin/perl

use warnings;

my $vocabFile = "file1.txt";
my %hashFR =();
open my $fh_infile, '<', $InFile or die "Can't open $InFile\n";

while ( my $Ligne = <$fh_infile> ) {
  if ( $Ligne =~ /(/ ) {
    my ($cle, $valeur) = split /(/, $Ligne;
    say $cle; 
    $h{$cle}  = $valeur;
  }     
}

我现在的问题是:如何提取箭头之前的词段并在哈希表中搜索它?

谢谢您的帮助

4

3 回答 3

2

你需要use strict。这将导致您的程序在遇到未声明的变量时失败$InFile(我假设您打算使用$vocabFile)。我将忽略您发布的代码中的这些类型的问题,因为一旦您打开严格,您就可以自己修复它们。

首先,现有代码存在一些逻辑问题。您似乎并没有真正使用括号中的数字作为哈希值存储,但如果您确实想使用它们,您可能应该去掉尾随)

    my ($cle, $valeur) = split /[()]/, $Ligne;

接下来,在使用字符串作为哈希键之前去除前导和尾随空格。可能认为"foo"and"foo "是同一个词,但 Perl 不会。

$cle =~ s/^\s+//;
$cle =~ s/\s+$//;

现在,您已经完成了大部分工作。您显然已经知道如何读入文件、如何使用split以及如何使用散列。你只需要把这些放在一起。读入第二个文件:

open my $fh2, "<", "file2" or die "Can't open file2: $!";

while (<$fh2>) {
    chomp;

...得到之前的部分->

    my ($left, $right) = split /->/;

...从键中去除前导和尾随空格

    $left =~ s/^\s+//;
    $left =~ s/\s+$//;

...如果您的哈希中存在密钥,则打印出整行

    print $_, "\n" if exists $hash{$left};

...完成后不要忘记关闭文件句柄

close $fh2;

(尽管正如 amon 指出的那样,这并不是绝对必要的,尤其是因为我们正在阅读而不是写作。有一个很好的PerlMonks 线程来处理这个主题。)

于 2013-09-20T20:32:56.317 回答
1

这可以通过直接从第一个文件的内容创建一个散列来非常简单地完成,然后读取第二个文件的每一行,检查散列以查看是否应该打印它。

use strict;
use warnings;
use autodie;

my %permitted = do {
  open my $fh, '<', 'f1.txt';
  map { /(.+?)\s+\(/, 1 } <$fh>;
};

open my $fh, '<', 'f2.txt';
while (<$fh>) {
  my ($phrase) = /(.+?)\s+->/;
  print if $permitted{$phrase};
}

输出

hello all -> salut (0.5)
hello all -> salut à tous (0.5)
hi all -> salut (0.63)
good bye all -> au revoir (0.09)
于 2013-09-20T20:38:10.763 回答
1
#!/usr/bin/perl

use strict; use warnings;
use Data::Dumper;

open my $FILE_1, '<', shift @ARGV;
open my $FILE_2, '<', shift @ARGV;

my @file1 = <$FILE_1>;
my @file2= <$FILE_2>;

close $FILE_1;
close $FILE_2;
# Store "segments" from the first file in hash:
my %first_file_hash = map { chomp $_; my ($a) = $_ =~ /^(.*?)\s*\(/; $a => 1 } @file1;

my @result;
# Process file2 content:
foreach my $line (@file2) {
    chomp $line;
    # Retrieve "segment" from the line:
    my ($string) = $line =~ /^(.*?)\s+->/;
    # If it is present in file1, store it for future usage:
    if ($string and $first_file_hash{ $string }) {
        push @result, $line;
    }
}

open my $F, '>', 'output.txt';
print $F join("\n", @result);
close $F;

print "\nDone!\n";

运行为:

perl script.pl file1.txt file2.txt

干杯!

于 2013-09-20T20:16:08.197 回答