首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl:从cp1251转换到utf8

Perl:从cp1251转换到utf8
EN

Stack Overflow用户
提问于 2015-10-14 03:39:44
回答 3查看 4.7K关注 0票数 3

我尝试将字符串转换为utf8。

代码语言:javascript
复制
#!/usr/bin/perl -w
use Encode qw(encode decode is_utf8);
$str = "\320\300\304\310\323\321 \316\320\300\312\313";
Encode::from_to($str, 'windows-1251', 'utf-8');
print "converted:\n$str\n";

在这种情况下,我得到了我所需要的:

代码语言:javascript
复制
# ./convert.pl
converted:
РАДИУС ОРАКЛ

但是如果我使用外部变量:

代码语言:javascript
复制
#!/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";

什么都没发生。

代码语言:javascript
复制
# ./convert.pl "\320\300\304\310\323\321 \316\320\300\312\313"
 converted:
\320\300\304\310\323\321 \316\320\300\312\313

这是第一个示例的转储:

代码语言:javascript
复制
SV = PV(0x1dceb78) at 0x1ded120
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1de7970 "\320\300\304\310\323\321 \316\320\300\312\313"\0
CUR = 12
LEN = 16

第二项是:

代码语言:javascript
复制
SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "\\320\\300\\304\\310\\323\\321 \\316\\320\\300\\312\\313"\0
CUR = 45
LEN = 48

我试过这个方法:

代码语言:javascript
复制
#!/usr/bin/perl -w
use Devel::Peek;
$str = pack 'C*', map oct, $ARGV[0] =~ /\\(\d{3})/g;
print Dump ($str);

# ./convert.pl "\320\300\304\310\323\321 \316\320\300\312\313"

SV = PV(0x1c1db78) at 0x1c3c110
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1c5e7e0 "\320\300\304\310\323\321\316\320\300\312\313"\0
CUR = 11
LEN = 48

但这又不是我所需要的。你能帮我得到像第一个剧本那样的结果吗?

在使用这个之后

代码语言:javascript
复制
($str = shift) =~ s/\\([0-7]+)/chr oct $1/eg

就像博罗丁建议的,我明白

代码语言:javascript
复制
SV = PVMG(0x13fa7f0) at 0x134d0f0
  REFCNT = 
  FLAGS = (SMG,POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x1347970 "\320\300\304\310\323\321 \316\320\300\312\313"\0
  CUR = 12
  LEN = 16
  MAGIC = 0x1358290 
    MG_VIRTUAL = &PL_vtbl_mglob
    MG_TYPE = PERL_MAGIC_regex_global(g)
    MG_LEN = -1
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-14 09:07:12

目前还不清楚您得到的输入是什么,从哪里得到,或者希望输出的是什么,但是您不应该将数据编码为UTF-8,以便在程序中使用,因为您希望处理字符而不是编码字节。您应该从发送到程序的任何外部编码中解码它,然后这样处理它。

听起来输入是Windows1251,输出是UTF-8 (?)我想反斜杠会分散注意力。文件中或键盘上没有反斜杠,对吗?因此,为了清晰起见,将基础改为十六进制,输入字符串如下所示

代码语言:javascript
复制
"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"

您希望将其转换为Perl字符串,对其做一些处理,并将其打印到输出。如果您在Linux机器上,并且希望从原始输入字节中显式地解码它,那么您需要编写如下内容

代码语言:javascript
复制
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;

输出

代码语言:javascript
复制
РАДИУС ОРАКЛ

但这是人为的情况。字符串实际上来自输入流,所以最好设置流的编码,而不需要手动解码。如果您正在读取STDIN,可以使用binmode,如下所示

代码语言:javascript
复制
binmode STDIN, 'encoding(Windows-1251)';

然后,来自STDIN的文本输入将隐式地从Windows1251编码的字节转换为字符串。或者,如果要在自己的句柄上打开文件,可以将编码放在open调用中

代码语言:javascript
复制
open my $fh, '<:encoding(Windows-1251)', $file or die $!;

然后您也不需要添加一个binmode

正如我说过的,我假设您的输出是UTF-8,并且在程序中超出了行

代码语言:javascript
复制
use open qw/ :std OUT :encoding(UTF-8) /;

将所有输出文件句柄设置为默认的UTF-8编码.:std还将内置句柄STDOUT和STDERR设置为UTF-8.如果这不是你想要的,你也想不出如何在你需要的时候设置它,那么请你问一问

票数 6
EN

Stack Overflow用户

发布于 2015-10-15 01:11:04

想想看:

代码语言:javascript
复制
$ perl -le 'print length("\320\300\304\310\323\321 \316\320\300\312\313")'
12

$ perl -le 'print length($ARGV[0])' "\320\300\304\310\323\321 \316\320\300\312\313"
45

在这里,我们接收给定字符串中的字符数。注意,当string在perl脚本中时,perl会根据它们的代码解释反斜杠符号。但是,如果反斜杠符号在perl脚本之外,则仅是shell符号,shell不会以某种方式解释它们,因此您得到了所提供的内容。

票数 0
EN

Stack Overflow用户

发布于 2015-10-15 05:48:58

将utf-8终端中输入的反斜杠和八进制数字转换为cp1251的几种简单方法:

代码语言:javascript
复制
$str = perl -e 'print "$ARGV[0]"' | iconv -f windows-1251;
print $str;

代码语言:javascript
复制
$str = pack "C*", map oct()? oct : 32, $ARGV[0] =~ / \d{3} | \s /gx;
print $str;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33116228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档