LINUX.ORG.RU

Что не так с кодировками? (боли-тред)

 ,


0

1

Есть файл в кодировке cp866, есть скрипт в кодировке utf8 (исходник).

Вот файл: http://zalil.ru/34490728

Вот скрипт:

#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Encode;

my $c = 0;
my $str = '';

open(my $fh, '<:encoding(cp866)', 'test.txt') or die "$!\n";;

while (($c++<10) && ($str = <$fh>)) {
    chomp $str;

    #my $norm = Encode::decode('cp866', $str);
    
    if ($str =~ m/^L#48595284#МУЗ Нефтекумская ЦРБ#$/) {
        print "TEST MATCHING: 1\n";
    } else {
        print "TEST MATCHING: 0\n";
    }
    print "is utf8: " . Encode::is_utf8($str) . "\n";

    Encode::_utf8_off($str);
    #print "$c>  $norm" . Encode::encode('utf8', $norm) . "\n";
    print "$c-" . Encode::is_utf8($str) . ">  $str\n";

}

В итоге регулярка никогда не срабатывает. Что бы я не делал.

Помогите побороть, пожалуйста.

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)

Encode::_utf8_off($str);

Зря, надо так:

binmode STDOUT, ':utf8';

Вот так у меня работает:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

open(my $fh, '<:encoding(cp866)', 'test.txt') or die "$!\n";;

binmode STDOUT, ':utf8';
for (my $c = 0; $c < 11; $c++) {
    my $str = <$fh>;
    last if (!$str);

    chomp $str;

    my $match = $str =~ m/L#48595284#МУЗ Нефтекумская ЦРБ#/ ? 'yes' : 'no';

print <<__LINE_SUMARY__;
$str
    MATCH: $match
__LINE_SUMARY__

}

Разница лишь в регулярке (отсутсвуют ^ и $).

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)

Фокус - в символах конца строки \r\n вместо \n:

$ cat test.pl
#!/usr/bin/perl
use warnings;
use strict;
use utf8;
use feature 'say';

use Encode;

open my $fh, "<:crlf:encoding(cp866)", $ARGV[0] or die $!;
binmode STDOUT, ":utf8";

while (<$fh>) {
        say /^L#48595284#МУЗ Нефтекумская ЦРБ#$/;
}
$ perl test.pl test.txt
1

AITap ★★★★★
()
Последнее исправление: AITap (всего исправлений: 2)
Ответ на: комментарий от KennyMinigun

Все дело в line separator: $/

$ file test.txt 
test.txt: Non-ISO extended-ASCII text, with CRLF line terminators

Видим - винда. Фиксим:

local $/ = "\r\n";

Fixed:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

open(my $fh, '<:encoding(cp866)', 'test.txt') or die "$!\n";

binmode STDOUT, ':utf8';
for (my $c = 0; $c < 11; $c++) {
    my $str = <$fh>;
    last if (!$str);

    {
        local $/ = "\r\n";
        chomp $str;

        my $match = $str =~ m/^L#48595284#МУЗ Нефтекумская ЦРБ#$/ ? 'yes' : 'no';

print <<__LINE_SUMARY__;
$str
    MATCH: $match
__LINE_SUMARY__
    }

}

KennyMinigun ★★★★★
()

да, все решило

local $/ = "\r\n";

А ведь я еще подумал, без концов в регулярке проверить... Но про такую фишку еще не знал. Спасибо.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Нет. chomp не убирает \r, т.к. $/ = «\n» by default. Вобщем делать надо как указали, либо руками:

open my $fh, "<", "/path/to/file" or die "open: $!";

while (<$fh>) {
  s/[\r\n]+$//;
  myfunc($_);
}
gh0stwizard ★★★★★
()
Ответ на: комментарий от AITap

:crlf

Век живи — век учись, блин.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.