0

「string1 string2 string3」という形式の行でファイルを読み込んで、いくつかの文字を置き換えます (ただし、すべての椅子は一度置換する必要があります)。たとえば、次のルールを使用します: tsch=> tch, ch> h , ki=> ky (ただし、ki が「単語」の末尾にある場合のみ) したがって、「tschaiki」は thaiky ではなく tchaiky になるはずです (これは、for ループまたはいくつかの単一の代替コマンドを使用する場合に発生します)。

この質問は以前に尋ねられ、perl でハッシュを作成することで解決されたことを知っています。

$line=<>
my %replace =(j=> "y", ss=> "s", u=> "ou", tsch=> "ch"); #short versions of the rules
my $regex = join "|", keys %replace;    

$regex = qr/$regex/;
$line=~s/($regex)/$replace{$1}/g;

これもこれまでのところ機能しますが、一部の文字は文字列の最後にある代替のみにする必要があります。しかし、これは問題を引き起こします: 私は前のコードを2番目の正規表現とハッシュで拡張しました:

 my %replace_end =(ia=> "iya", ki=> "ky",ei=> "ey" );
 my $regex_end = join "|", keys %replace_end;
 $regex_end = qr/$regex_end/; 
 $line=~s/($regex_end)$/$replace_end{$1}/g;  # saying just to substitute at the end 

私のコード全体は次のとおりですが、例外になるか、末尾が無視されます(ファイル処理とwhileループのないコードは実際に機能したと思います):

#!/usr/bin/perl
use strict;
use warnings;

open(INP,"<:utf8","dt_namen.txt"); 
open(OUT,">:utf8","dt_zu_engl.txt");

my %replace =(j=> "y", ss=> "s", tsch=> "ch", sch => "sh", c => "k", J="Y", Ss=>"s"); 
 my $regex = join "|", keys %replace;  
 $regex = qr/$regex/;

 my %replace_end =(ki=> "ky",ei=> "ey" );
 my $regex_end = join "|", keys %replace_end;
 $regex_end = qr/$regex_end/; 

while(my $line= <INP>){
 $line=~s/($regex)/$replace{$1}/g;
 $line=~s/($regex_end)$/$replace_end{$1}/g;  # saying just to substitute at the end 
 print $line;
 print OUT "$line";
}
close INP;
close OUT;
4

1 に答える 1

3

あなたのコードには、置換の順序が定義されていないという潜在的な問題があります。2 つのパターンが同じ位置で一致する場合、どちらが一致するかはわかりません。それはすべて正規表現でどちらが最初に来るかに依存し、ハッシュには定義された順序がないため、現時点では保証された動作はありません。

sort正規表現を作成するときにa を実行して、これを修正します。

my $regex = join "|", sort {length($b) <=> length($a)} keys %replace;

これにより、用語が長さの降順に並べ替えられるため、常に最も長い用語が最初に一致するようになります。

更新:文字列の末尾のみを置き換えるには、次のようにします。

my $regex_end = join "|", map { qr/$_$/ } keys %replace_end;

$各用語の末尾に (文字列の末尾に一致する) を付けます。

または、単語の末尾のみを置換する場合は、次のようにします。

my $regex_end = join "|", map { qr/$_\b/ } keys %replace_end;
于 2013-04-29T10:52:08.653 に答える