Perl:从cp1251转换为utf8

Perl:从cp1251转换为utf8,perl,encoding,utf-8,cp1251,Perl,Encoding,Utf 8,Cp1251,我尝试将字符串转换为utf8 #!/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"; 在这种情况下,我得到了我需要的: # ./convert.pl converted: РА

我尝试将字符串转换为utf8

#!/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";
在这种情况下,我得到了我需要的:

# ./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 "\320\300\304\310\323\321 \316\320\300\312\313"
 converted:
\320\300\304\310\323\321 \316\320\300\312\313
这是第一个示例的转储:

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
第二点:

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
我尝试过这种方法:

#!/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
但这又不是我需要的。你能帮我得到第一个脚本中的结果吗


用了这个

($str = shift) =~ s/\\([0-7]+)/chr oct $1/eg
正如博罗丁所说,我明白了

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

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

听起来输入是Windows-1251,输出是UTF-8(?),我假设反斜杠是一种干扰。文件中没有反斜杠,键盘上也没有键入反斜杠,是吗?为了清晰起见,将基数改为十六进制,输入字符串如下

"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"
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;
binmode STDIN, 'encoding(Windows-1251)';
您需要将其转换为Perl字符串,对其执行一些操作,然后将其打印到输出中。如果您在Linux机器上,并且希望从原始输入字节显式解码它,那么您需要编写如下代码

"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"
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;
binmode STDIN, 'encoding(Windows-1251)';
输出 但这是人为造成的。字符串实际上来自输入流,因此最好设置流的编码,而不要考虑手动解码。如果您正在从STDIN读取,可以使用
binmode
,如下所示

"\xD0\xC0\xC4\xC8\xD3\xD1\x20\xCE\xD0\xC0\xCA\xCB"
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;
binmode STDIN, 'encoding(Windows-1251)';
然后,来自STDIN的文本输入将从Windows-1251编码的字节隐式转换为字符串。或者,如果您正在用自己的句柄打开一个文件,您可以将编码放入
open
调用中

open my $fh, '<:encoding(Windows-1251)', $file or die $!;
将所有输出文件句柄设置为默认UTF-8编码。
:std
还将内置句柄STDOUT和STDERR设置为UTF-8。如果这不是您想要的,并且您不知道如何在需要时设置它,那么请询问想想:

$ 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
这里我们接收给定字符串中的字符数。
请注意,当字符串位于perl脚本中时,perl会根据反斜杠符号的代码来解释它们。但是,如果反斜杠符号在perl脚本之外,则它们只是shell符号,shell不会以某种方式对它们进行解释,因此您可以准确地得到您给出的内容。

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

$str = perl -e 'print "$ARGV[0]"' | iconv -f windows-1251;
print $str;


你的输入格式到底是什么?它能包含除反斜杠+八进制数以外的任何特殊序列吗?当您
打包时,您必须退出转义。输入应该是
“\\320\\300\\304\\310\\323\\321\\316\\320\\300\\312\\313”
如果你想要空间,你需要使用八进制空间字符(040),
“\\320\\300\\304\\310\\323\\321\\040\\316\\320\\300\\312\\313”
你说你的第三个例子“不是我需要的”但是字符串与第一个示例相同,您说它是正确的,只是删除了空格。它到底出了什么问题?能用吗
($str=shift)=~s/\\([0-7]+)/chr oct$1/eg
@melpomene输入格式是utf-8格式的字符串,但此字符串包含来自