之前我正在循环中进行循环,如果匹配,它将替换第二个循环文件中的整个字符串。现在我的情况略有不同。我试图用第二个循环中的字符串替换第一个循环中的子字符串。它们都是csv文件和分号分隔的。我试图替换的是特殊字符:从数字代码到字符本身第一个文件看起来像:
1;2;blałblabla ąbla;7;8
3;4;bląblabla;9;10
2;3;blablablaąał8;9
,第二个文件包含数字代码和相应的字符:
Ą;Ą
ą;ą
Ǟ;Ǟ
Á;Á
á;á
Â;Â
ł;ł
第二个文件中的第一个分号属于相应字符的数字代码,不应用于拆分文件。结果应该是:
1;2;blałblabla ąbla;7;8
3;4;bląblabla;9;10
2;3;blablablaąał;8;9
这是我的代码。我该如何解决这个问题?
use strict;
use warnings;
my $inputfile1 = shift || die "input/output!\n";
my $inputfile2 = shift || die "input/output!\n";
my $outputfile = shift || die "output!\n";
open my $INFILE1, '<', $inputfile1 or die "Used/Not found :$!\n";
open my $INFILE2, '<', $inputfile2 or die "Used/Not found :$!\n";
open my $OUTFILE, '>', $outputfile or die "Used/Not found :$!\n";
my $infile2_pos = tell $INFILE2;
while (<$INFILE1>) {
s/"//g;
my @elements = split /;/, $_;
seek $INFILE2, $infile2_pos, 0;
while (<$INFILE2>) {
s/"//g;
my @loopelements = split /;/, $_;
#### The problem part ####
if (($elements[2] =~ /\&\#\d{3}\;/g) and (($elements[2]) eq ($loopelements[0]))){
$elements[2] =~ s/(\&\#\d{3}\;)/$loopelements[1]/g;
print "$2. elements[2]\n";
}
#### End problem part #####
}
my $output_line = join(";", @elements);
print $OUTFILE $output_line;
#print "\n"
}
close $INFILE1;
close $INFILE2;
close $OUTFILE;
exit 0;
答案 0 :(得分:2)
假设您的字符代码是标准的Unicode实体,最好使用HTML::Entities
对其进行解码。
此程序处理您在第一个文件中显示的数据,并完全忽略第二个文件。输出似乎是你想要的。
use strict;
use warnings;
use HTML::Entities 'decode_entities';
binmode STDOUT, ":utf8";
while (<DATA>) {
print decode_entities($_);
}
__DATA__
1;2;blałblabla ąbla;7;8
3;4;bląblabla;9;10
2;3;blablablaąał8;9
<强>输出强>
1;2;blałblabla ąbla;7;8
3;4;bląblabla;9;10
2;3;blablablaąał8;9
答案 1 :(得分:0)
您在每次@elements
出现时都会将;
拆分,然后将其删除。您不会在数据中找到它,Regexp中的分号永远不会匹配,因此不会进行任何替换。
无论如何,使用seek
对我来说有点令人不安。由于您有合理数量的替换代码(&lt; 5000),您可以考虑将它们放入哈希:
my %subst;
while(<$INFILE2>){
/^&#(\d{3});;(.*)\n/;
$subst{$1} = $2;
}
然后我们可以这样做:
while(<$INFILE1>){
s| &# (\d{3}) | $subst{$1} // "&#$1" |egx;
# (don't try to concat undef
# when no substitution for our code is defined)
print $OUTFILE $_;
}
如果在INFILE1中的任何地方都要进行替换,我们不必拆分文件或将其视为CSV数据。我的解决方案应该加快一点(仅解析INFILE2一次)。在这里,我假设您的输入数据是正确的,数字代码不是以分号结尾,而是按长度终止。您可能希望从正则表达式中删除它。(即m/&#\d{3}/
)
如果您在使用字符编码时遇到问题,可能需要使用以下命令打开文件:uft8和/或use Encode
或类似文件。