Perl:从 cp1251 转换为 utf8
Perl: converting from cp1251 to utf8
我尝试将字符串转换为 utf8。
#!/usr/bin/perl -w
use Encode qw(encode decode is_utf8);
$str = "004031 60023";
Encode::from_to($str, 'windows-1251', 'utf-8');
print "converted:\n$str\n";
在这种情况下,我得到了我需要的东西:
# ./convert.pl
converted:
РАДИУС ОРАКЛ
但是如果我使用外部变量:
#!/usr/bin/perl -w
use Encode qw(encode decode is_utf8);
$str = $ARGV[0];
Encode::from_to($str, 'windows-1251', 'utf-8');
print "converted:\n$str\n";
没有任何反应。
# ./convert.pl "004031 60023"
converted:
004031 60023
这是第一个例子的转储:
SV = PV(0x1dceb78) at 0x1ded120
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1de7970 "004031 60023"[=14=]
CUR = 12
LEN = 16
第二个:
SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "\320\300\304\310\323\321 \316\320\300\312\313"[=15=]
CUR = 45
LEN = 48
我试过这个方法:
#!/usr/bin/perl -w
use Devel::Peek;
$str = pack 'C*', map oct, $ARGV[0] =~ /\(\d{3})/g;
print Dump ($str);
# ./convert.pl "004031 60023"
SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "00403160023"[=16=]
CUR = 11
LEN = 48
但这又不是我所需要的。你能帮我得到第一个脚本中的结果吗?
使用后
($str = shift) =~ s/\([0-7]+)/chr oct /eg
按照 Borodin 的建议,我明白了
SV = PVMG(0x13fa7f0) at 0x134d0f0
REFCNT =
FLAGS = (SMG,POK,pPOK)
IV = 0
NV = 0
PV = 0x1347970 "004031 60023"[=18=]
CUR = 12
LEN = 16
MAGIC = 0x1358290
MG_VIRTUAL = &PL_vtbl_mglob
MG_TYPE = PERL_MAGIC_regex_global(g)
MG_LEN = -1
不清楚您从哪里得到什么输入,或者您希望输出什么,但是您不应该将数据编码为 UTF-8 以便在程序中使用,因为您想要处理 个字符 而不是编码字节。您应该只从发送给程序的任何外部编码解码它并像那样使用它
听起来输入是 Windows-1251,输出是 UTF-8 (?),我认为反斜杠会分散注意力。文件中没有反斜杠或在键盘上输入了吗?因此,为清楚起见,将基数更改为十六进制,您的输入字符串如下所示
"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"
并且您想将其转换为 Perl 字符串,对其执行一些操作,然后将其打印到输出中。如果你在 Linux 机器上并且你想从原始输入字节显式解码它,那么你需要写这样的东西
use utf8;
use strict;
use warnings;
use feature 'say';
use open qw/ :std OUT :encoding(UTF-8) /;
use Encode qw/ decode /;
my $str = "\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB";
$str = decode('Windows-1251', $str);
say $str;
输出
РАДИУС ОРАКЛ
但这是人为的情况。该字符串实际上来自输入流,因此最好设置流的编码并忘记手动解码。如果你从 STDIN 读取,你可以使用 binmode
,像这样
binmode STDIN, 'encoding(Windows-1251)';
然后从 STDIN 输入的文本将从 Windows-1251 编码的字节隐式转换为字符串。或者,如果您在自己的句柄上打开文件,则可以将编码放在 open
调用
中
open my $fh, '<:encoding(Windows-1251)', $file or die $!;
然后你也不需要添加 binmode
正如我所说,我假设您的输出是 UTF-8,并且在
行上方的程序中
use open qw/ :std OUT :encoding(UTF-8) /;
将所有 输出 文件句柄设置为具有默认的 UTF-8 编码。 :std
还将内置句柄 STDOUT 和 STDERR 设置为 UTF-8。如果这不是您想要的,并且您不知道如何根据需要进行设置,请询问
想想这个:
$ perl -le 'print length("004031 60023")'
12
$ perl -le 'print length($ARGV[0])' "004031 60023"
45
在这里我们收到给定字符串中的字符数。
请注意,当字符串在 inside perl 脚本中时,perl 会根据其代码解释反斜杠符号。但是如果反斜杠符号在 perl 脚本之外,那么它们只是 shell 符号 并且 shell 不会以某种方式解释它们,所以你得到的正是你所提供的。
将 utf-8 终端中输入的反斜杠和八进制数字转换为 cp1251 的几个简单方法:
$str = perl -e 'print "$ARGV[0]"' | iconv -f windows-1251;
print $str;
或
$str = pack "C*", map oct()? oct : 32, $ARGV[0] =~ / \d{3} | \s /gx;
print $str;
我尝试将字符串转换为 utf8。
#!/usr/bin/perl -w
use Encode qw(encode decode is_utf8);
$str = "004031 60023";
Encode::from_to($str, 'windows-1251', 'utf-8');
print "converted:\n$str\n";
在这种情况下,我得到了我需要的东西:
# ./convert.pl
converted:
РАДИУС ОРАКЛ
但是如果我使用外部变量:
#!/usr/bin/perl -w
use Encode qw(encode decode is_utf8);
$str = $ARGV[0];
Encode::from_to($str, 'windows-1251', 'utf-8');
print "converted:\n$str\n";
没有任何反应。
# ./convert.pl "004031 60023"
converted:
004031 60023
这是第一个例子的转储:
SV = PV(0x1dceb78) at 0x1ded120
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1de7970 "004031 60023"[=14=]
CUR = 12
LEN = 16
第二个:
SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "\320\300\304\310\323\321 \316\320\300\312\313"[=15=]
CUR = 45
LEN = 48
我试过这个方法:
#!/usr/bin/perl -w
use Devel::Peek;
$str = pack 'C*', map oct, $ARGV[0] =~ /\(\d{3})/g;
print Dump ($str);
# ./convert.pl "004031 60023"
SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "00403160023"[=16=]
CUR = 11
LEN = 48
但这又不是我所需要的。你能帮我得到第一个脚本中的结果吗?
使用后
($str = shift) =~ s/\([0-7]+)/chr oct /eg
按照 Borodin 的建议,我明白了
SV = PVMG(0x13fa7f0) at 0x134d0f0
REFCNT =
FLAGS = (SMG,POK,pPOK)
IV = 0
NV = 0
PV = 0x1347970 "004031 60023"[=18=]
CUR = 12
LEN = 16
MAGIC = 0x1358290
MG_VIRTUAL = &PL_vtbl_mglob
MG_TYPE = PERL_MAGIC_regex_global(g)
MG_LEN = -1
不清楚您从哪里得到什么输入,或者您希望输出什么,但是您不应该将数据编码为 UTF-8 以便在程序中使用,因为您想要处理 个字符 而不是编码字节。您应该只从发送给程序的任何外部编码解码它并像那样使用它
听起来输入是 Windows-1251,输出是 UTF-8 (?),我认为反斜杠会分散注意力。文件中没有反斜杠或在键盘上输入了吗?因此,为清楚起见,将基数更改为十六进制,您的输入字符串如下所示
"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"
并且您想将其转换为 Perl 字符串,对其执行一些操作,然后将其打印到输出中。如果你在 Linux 机器上并且你想从原始输入字节显式解码它,那么你需要写这样的东西
use utf8;
use strict;
use warnings;
use feature 'say';
use open qw/ :std OUT :encoding(UTF-8) /;
use Encode qw/ decode /;
my $str = "\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB";
$str = decode('Windows-1251', $str);
say $str;
输出
РАДИУС ОРАКЛ
但这是人为的情况。该字符串实际上来自输入流,因此最好设置流的编码并忘记手动解码。如果你从 STDIN 读取,你可以使用 binmode
,像这样
binmode STDIN, 'encoding(Windows-1251)';
然后从 STDIN 输入的文本将从 Windows-1251 编码的字节隐式转换为字符串。或者,如果您在自己的句柄上打开文件,则可以将编码放在 open
调用
open my $fh, '<:encoding(Windows-1251)', $file or die $!;
然后你也不需要添加 binmode
正如我所说,我假设您的输出是 UTF-8,并且在
行上方的程序中use open qw/ :std OUT :encoding(UTF-8) /;
将所有 输出 文件句柄设置为具有默认的 UTF-8 编码。 :std
还将内置句柄 STDOUT 和 STDERR 设置为 UTF-8。如果这不是您想要的,并且您不知道如何根据需要进行设置,请询问
想想这个:
$ perl -le 'print length("004031 60023")'
12
$ perl -le 'print length($ARGV[0])' "004031 60023"
45
在这里我们收到给定字符串中的字符数。 请注意,当字符串在 inside perl 脚本中时,perl 会根据其代码解释反斜杠符号。但是如果反斜杠符号在 perl 脚本之外,那么它们只是 shell 符号 并且 shell 不会以某种方式解释它们,所以你得到的正是你所提供的。
将 utf-8 终端中输入的反斜杠和八进制数字转换为 cp1251 的几个简单方法:
$str = perl -e 'print "$ARGV[0]"' | iconv -f windows-1251;
print $str;
或
$str = pack "C*", map oct()? oct : 32, $ARGV[0] =~ / \d{3} | \s /gx;
print $str;