4

2つのファイルがあります。1つはテキストを含み、もう1つはキー/ハッシュ値を含みます。キーの出現箇所をハッシュ値に置き換えたい。次のコードはこれを実行します。私が知りたいのは、使用しているforeachループよりも優れた方法があるかどうかです。

皆さんありがとう

編集:私はそれを使用して少し奇妙であることを知っています

s/\n//;
s/\r//;

chompの代わりに、これは行末文字が混在するファイル(WindowsとLinuxの両方で編集)で機能し、chomp(私は思う)は機能しません。

キー/ハッシュ値を含むファイル(hash.tsv):

strict  $tr|ct
warnings    w@rn|ng5
here    h3r3

テキスト付きのファイル(doc.txt):

Do you like use warnings and strict?
I do not like use warnings and strict.
Do you like them here or there?
I do not like them here or there?
I do not like them anywhere.
I do not like use warnings and strict.
I will not obey your good coding practice edict. 

perlスクリプト:

#!/usr/bin/perl

use strict;
use warnings;
open (fh_hash, "<", "hash.tsv") or die "could not open file $!";
my %hash =();
while (<fh_hash>)
{
    s/\n//;
    s/\r//;
    my @tmp_hash = split(/\t/);
    $hash{ @tmp_hash[0] } = @tmp_hash[1];
}
close (fh_hash);
open (fh_in, "<", "doc.txt") or die "could not open file $!";
open (fh_out, ">", "doc.out") or die "could not open file $!";
while (<fh_in>)
{
    foreach my $key ( keys %hash )
    {
        s/$key/$hash{$key}/g;
    }
    print fh_out;
}
close (fh_in);
close (fh_out);
4

2 に答える 2

2

ファイル全体を変数に読み込んで、key-valごとにすべてのオカレンスを一度に置き換えることができます。

何かのようなもの:

use strict;
use warnings;

use YAML;
use File::Slurp;
my $href = YAML::LoadFile("hash.yaml");
my $text = read_file("text.txt");

foreach (keys %$href) {
    $text =~ s/$_/$href->{$_}/g;
}
open (my $fh_out, ">", "doc.out") or die "could not open file $!";
print $fh_out $text;
close $fh_out;

生成:

Do you like use w@rn|ng5 and $tr|ct?
I do not like use w@rn|ng5 and $tr|ct.
Do you like them h3r3 or th3r3?
I do not like them h3r3 or th3r3?
I do not like them anywh3r3.
I do not like use w@rn|ng5 and $tr|ct.
I will not obey your good coding practice edict. 

コードを短縮するために、YAMLを使用し、入力ファイルを次のように置き換えました。

strict: $tr|ct
warnings: w@rn|ng5
here: h3r3

ファイル全体を変数に読み込むためにFile::Slurpを使用しました。もちろん、File::Slurpなしでファイルを「スラップ」することができます。

my $text;
{
    local($/); #or undef $/;
    open(my $fh, "<", $file ) or die "problem $!\n";
    $text = <$fh>;
    close $fh;
}
于 2012-07-19T19:17:43.613 に答える
2

1つの問題

for my $key (keys %hash) {
    s/$key/$hash{$key}/g;
}

正しく処理されないのですか

foo => bar
bar => foo

交換する代わりに、すべて「foo」またはすべて「bar」になり、どちらを制御することもできません。

# Do once, not once per line
my $pat = join '|', map quotemeta, keys %hash;

s/($pat)/$hash{$1}/g;

あなたも処理したいかもしれません

foo  => bar
food => baz

おそらく「吟遊詩人」で終わるのではなく、最も長くかかることによって。

# Do once, not once per line
my $pat =
   join '|',
    map quotemeta,
     sort { length($b) <=> length($a) }
      keys %hash;

s/($pat)/$hash{$1}/g;
于 2012-07-19T21:06:58.650 に答える