我编写了一个 Perl 脚本,它有两个输入文件:
第一个文件的每行都有短语,然后是括号之间的值。这是一个例子:
hello all (0.5) hi all (0.63) good bye all (0.09)
第二个文件有一个规则列表。例如:
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;
}
}
我现在的问题:如何提取箭头之前的单词段并在哈希表中搜索它?
感谢您的帮助
最佳答案
您需要使用严格
。当您的程序遇到像 $InFile
这样的未声明变量时,这会导致您的程序失败(我假设您打算使用 $vocabFile
)。我将忽略您发布的代码中的这些类型的问题,因为一旦您打开严格,您就可以自行修复它们。
首先,您现有的代码存在一些逻辑问题。您似乎实际上并没有使用存储为哈希值的括号中的数字,但如果您确实想使用它们,您可能应该去掉尾随的 )
:
my ($cle, $valeur) = split /[()]/, $Ligne;
接下来,在使用字符串作为哈希键之前去除前导和尾随空格。 您可能认为“foo”
和“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 thread 处理这个主题。)
关于Perl 脚本在哈希表中搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18924656/