如何在 perl v5.24 中获取 unicode 代码点?

Dav*_*eks 5 unicode perl ord

我想记录作为参数剪切并粘贴到 bash 中的字符串的十六进制 unicode 代码点。ord 不这样做;ord 似乎只在 ascii 范围内工作。

\n\n

我发现的关于 ord 的大部分内容至少已有六年或更久了,并且不再相关,因为我使用的是 v5.24,我读过的 v5.24 内置了 unicode 支持。\n在 python 中,它是琐碎的:

\n\n
\nfor i in unicode(sys.argv[1], \'utf-8\'):\n    print i.encode("utf_16_be").encode("hex")\n
Run Code Online (Sandbox Code Playgroud)\n\n

它在 bash 中工作。\n我认为问题在于 ord 函数本身,它似乎没有针对 unicode 进行更新。

\n\n
\n# ord.pl does not provide the unicode code point for a pasted variable.\nuse strict;\nuse warnings;\n#use charnames (); #nope.\n#use feature \'unicode_strings\'; #nope.  Already automatically using as of v5.12.\n#use utf8; #nope.\n#binmode(STDOUT, ":encoding(UTF-8)"); #nope.\n\nmy $arg = "";\n\nforeach $arg  (@ARGV) {\n  print $arg . " is " . ord($arg) . " in code.\\n";  # seems to me ord is ascii only.\n  #utf8::encode($arg);  #nope.\n  #print unpack("H*", $arg) . "\\n";  #nope.\n\n  #printf "%vX\\n", $arg;  #nope.\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

得到:

\n\n
david@A8DT01:~/bin$ ord.pl A B C D a b c d \\  \\\\ \xe2\x80\xa6 \xe2\x80\x94 \xef\x80\xa8 \xe2\x82\xac\nA is 65 in code.\n41\nB is 66 in code.\n42\nC is 67 in code.\n43\nD is 68 in code.\n44\na is 97 in code.\n61\nb is 98 in code.\n62\nc is 99 in code.\n63\nd is 100 in code.\n64\n  is 32 in code.\n20\n\\ is 92 in code.\n5c\n\xe2\x80\xa6 is 226 in code.\nc3a2c280c2a6\n\xe2\x80\x94 is 226 in code.\nc3a2c280c294\n\xef\x80\xa8 is 239 in code.\nc3afc280c2a8\n\xe2\x82\xac is 226 in code.\nc3a2c282c2ac\ndavid@A8DT01:~/bin$\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想得到 python 中得到的输出:

\n\n
david@A8DT01:~/bin$ python code-points.py "ABCDabcd \\ \xe2\x80\xa6 \xe2\x80\x94 \xef\x80\xa8 \xe2\x82\xac"\n0041\n0042\n0043\n0044\n0061\n0062\n0063\n0064\n0020\n005c\n0020\n2026\n0020\n2014\n0020\nf028\n0020\n20ac\ndavid@A8DT01:~/bin$\n
Run Code Online (Sandbox Code Playgroud)\n

Gri*_*nnz 5

不是ord的问题,而是encoding的问题。来自命令行的输入通常是 UTF-8 编码的,并且 ord 只接受单个字符,而不是多字节字符串。您可以使用-CA开关自动解码@ARGV(或者-CSA使 STDOUT 也针对终端进行编码),或者在脚本中执行。

use strict;
use warnings;
use Encode;
foreach my $arg (@ARGV) {
  my $decoded = decode 'UTF-8', $arg;
  print $arg . " is " . ord($decoded) . " in code.\n";
}
Run Code Online (Sandbox Code Playgroud)

但是,您的 python 脚本正在做一些非常不同的事情,它返回编码为 UTF-16BE 的字符串的十六进制表示形式,而不是 unicode 字符的十进制序数。您也可以在 Perl 中执行此操作。

use strict;
use warnings;
use Encode;
foreach my $arg (@ARGV) {
  my $utf16 = encode 'UTF-16BE', decode 'UTF-8', $arg;
  print $arg . " is " . sprintf("%vX", $utf16) . " in code.\n";
}
Run Code Online (Sandbox Code Playgroud)