0

早些时候我正在处理循环中的循环,如果匹配,它将替换第二个循环文件​​中的整个字符串。现在我的情况略有不同。我正在尝试用第二个循环中的字符串替换第一个循环中的子字符串。它们都是 csv 文件和分号分隔。我要替换的是特殊字符:从数字代码到字符本身 第一个文件如下所示:

1;2;bla&#322blabla &#261bla;7;8
3;4;bl&#261blabla;9;10
2;3;blablabla&#261ał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;
4

2 回答 2

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&#322blabla &#261bla;7;8
3;4;bl&#261blabla;9;10
2;3;blablabla&#261a&#322;8;9

输出

1;2;blałblabla ąbla;7;8
3;4;bląblabla;9;10
2;3;blablablaąał8;9
于 2012-07-13T15:34:35.100 回答
0

@elements在每次出现时拆分您的;,然后将其删除。您不会在您的数据中找到它,您的正则表达式中的分号永远不会匹配,因此不会进行任何替换。

无论如何,使用seek对我来说有点令人不安。由于您有合理数量的替换代码(<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或类似文件打开文件。

于 2012-07-13T13:34:36.723 回答