我想在一个文件中读取,使用以下形式的行:“string1 string2 string3”并替换掉几个字符,(但每个主席应该替换一次) 例如,这些规则:tsch => tch,ch> h,ki => ky(但是,如果ki在'word'的末尾) 所以“tschaiki”应该得到tchaiky而不是thaiky(当使用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;
这对我来说到目前为止也有用,但我希望在字符串的末尾只能替换一些字符。但这会导致问题: 我已经扩展了之前的代码,第二个正则表达式和哈希仅用于结尾:
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;
答案 0 :(得分:3)
您的代码存在潜在问题,因为未定义替换顺序。如果两个模式在同一位置匹配,则不知道哪个模式匹配。这一切都取决于正则表达式中的第一个,并且哈希没有定义的顺序,所以现在没有保证的行为。
通过在构造正则表达式时执行sort
来解决此问题:
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;