0

以前、ループ内のループに取り組んでいましたが、一致した場合、2 番目のループ ファイルの文字列全体が置き換えられました。今、私は少し異なる状況にあります。最初のループの部分文字列を 2 番目のループの文字列に置き換えようとしています。どちらも csv ファイルで、セミコロンで区切られています。私が置き換えようとしているのは特殊文字です:数値コードから文字自体まで最初のファイルは次のようになります:

1;2;bla&#322blabla &#261bla;7;8
3;4;bl&#261blabla;9;10
2;3;blablabla&#261ał8;9

2 番目のファイルには、数値コードと対応する文字が含まれています。

Ą;Ą
ą;ą
Ǟ;Ǟ
Á;Á
á;á
Â;Â
ł;ł

2 番目のファイルの最初のセミコロンは、対応する文字の数値コードに属しており、ファイルの分割には使用しないでください。結果は次のようになります。

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それらをデコードするために使用する方がよいでしょう。

このプログラムは、最初のファイルに表示されたデータを処理し、 2番目のファイルを完全に無視します。出力はあなたが望むもののようです。

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の解析は1回だけです)。ここでは、入力データが正しく、数値コードがセミコロンではなく長さで終了していると仮定しました。あなたの正規表現からそれを削除したいかもしれません.(つまりm/&#\d{3}/)

文字エンコーディングに問題がある場合は、:uft8 などでファイルを開くことをお勧めしますuse Encode

于 2012-07-13T13:34:36.723 に答える