2

2 つの入力ファイルを持つ Perl スクリプトをプログラムしました。

  1. 最初のファイルには、各行にフレーズがあり、次に括弧内に値があります。ここに例があります:

    hello all (0.5)
    hi all (0.63)
    good bye all (0.09)
    
  2. 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)
    

スクリプトは 2 番目のファイルを読み取る必要があり、各行で矢印の前のフレーズを抽出し (たとえば、1 行目: 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"はと を"foo "同じ言葉だと思うかもしれませんが、Perl はそうではありません。

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

さて、あなたはすでにほとんどそこまで来ています。splitファイルを読み込む方法、 を使用する方法、およびハッシュを使用する方法を既に知っていることは明らかです。これらをすべてまとめる必要があります。2 番目のファイルを読み込みます。

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
#!/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 に答える
1

これは、最初のファイルの内容から直接ハッシュを作成し、2 番目のファイルの各行を読み取り、ハッシュをチェックして出力する必要があるかどうかを確認することで、非常に簡単に実行できます。

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 に答える