如何在 unicode 形式之间进行转换:字符串、名称、数字

Posted

技术标签:

【中文标题】如何在 unicode 形式之间进行转换:字符串、名称、数字【英文标题】:How to convert between the unicode forms: string, name, number 【发布时间】:2022-01-14 12:03:39 【问题描述】:

我最近使用 unicode 比较频繁,想知道是否有命令行工具可以在其形式之间转换 unicode。

很高兴能够说:

uni_convert "☃" --string

并且知道字符串在 unicode 中定义为“SNOWMAN”。

【问题讨论】:

【参考方案1】:

Perl 的Unicode-Tussle 分发版附带有用的uniprops

$ uniprops '☃'
U+2603 ‹☃› \NSNOWMAN
...

$ uniprops 'U+2603'
U+2603 ‹☃› \NSNOWMAN
...

$ uniprops 'SNOWMAN'
U+2603 ‹☃› \NSNOWMAN
...

如果您正在编写代码,则需要charnames。

Input  To get $code
=====  ==============================
$char  ord($char)
$name  charnames::vianame($name)

Input  To get $char                    
=====  ==============================
$code  chr($code)
$name  chr(charnames::vianame($name))

Input  To get $name
=====  ==============================
$code  charnames::viacode($code)
$char  charnames::viacode(ord($char))

vianame 接受官方别名(例如,LF 代表 LINEFEED)。如果希望接受它,您需要自己解析 U+ 符号。 ($code = hex(s/^U\+//r);)

例子:

use strict;
use warnings;
use feature      qw( say );
use experimental qw( regex_sets );

use utf8;                              # Source encoded using UTF-8.
use open ":std", ":encoding(UTF-8)";   # Terminal provides/expects UTF-8.

use charnames qw( :full );
use Encode    qw( decode_utf8 );

@ARGV == 1
   or die("usage\n");

my $s = decode_utf8($ARGV[0]);

for my $cp ( unpack "W*", $s ) 
   my $ch = chr($cp);
   if ( $ch =~ /(?[ \pPrint - \pMark ])/ )    # Not sure if good enough.
      printf "‹%s› ", $ch;
    else 
      print "--- ";
   

   printf "U+%X ", $cp;

   say charnames::viacode($cp);

$ uni_id ☃
‹☃› U+2603 SNOWMAN

$ uni_id çà
‹ç› U+E7 LATIN SMALL LETTER C WITH CEDILLA
‹à› U+E0 LATIN SMALL LETTER A WITH GRAVE

其他资源:

Unicode::UCD

提供对Unicode Character Database 中的信息的访问权限。

Unicode Standard 不仅仅是字符和属性。

perluniprops

unichars 来自Unicode-Tussle(例如unichars '\pHiragana'

【讨论】:

@ikegani: metacpan.org/dist/charnames 为我返回“未找到”页面。我建议改为metacpan.org/pod/charnames。 @EdSabol 已修复。【参考方案2】:

这里有一个 awk 可以做到这一点。

从提供最新名称的 unicode.org 下载 this file。

然后:

q=$(printf '%x\n' \'☃)
awk '/^[[:xdigit:]]+/
    str=$0
    sub(/^[[:xdigit:]]+[[:blank:]]+/,"",str)
    names[$1]=str

END print names[q] 
' q="$q" names.txt

打印:

SNOWMAN

如果你想走另一条路:

cp=$(awk '/^[[:xdigit:]]+/
    str=$0
    sub(/^[[:xdigit:]]+[[:blank:]]+/,"",str)
    other_names[str]=$1

END print other_names[q] 
' q="SNOWMAN" names.txt)

echo -e "\u$cp"

打印:

如果您有 GNU awk,您可以轻松地将十六进制索引转换为十进制并可以从内部打印。这允许通过定义 qr 来使用单个源文件并以一种或另一种方式使用:

gawk '/^[[:xdigit:]]+/
    str=$0
    sub(/^[[:xdigit:]]+[[:blank:]]+/,"",str)
    names[$1]=str
    other_names[str]=$1

END print q ? names[q] : sprintf("%c", strtonum("0x" other_names[r])) 
' r='SNOWMAN' names.txt
☃

gawk '/^[[:xdigit:]]+/
    str=$0
    sub(/^[[:xdigit:]]+[[:blank:]]+/,"",str)
    names[$1]=str
    other_names[str]=$1

END print q ? names[q] : sprintf("%c", strtonum("0x" other_names[r])) 
' q=$(printf '%x\n' \'☃) names.txt
SNOWMAN

【讨论】:

换个方式怎么样? 我不知道有这样的文件。很高兴知道? Re "从提供最新名称的 unicode.org 下载此文件。",别忘了aliases【参考方案3】:

我将代码分成一个文件并创建了一个 repo: https://github.com/poti1/uni_convert

【讨论】:

为什么不直接使用一个实际的 perl 脚本文件,而不是一个用 shell 函数包裹的巨大的单行代码? 哦,Term::ANSIColor 代替硬编码的转义序列很有用。 我倾向于将这些添加到我的 bashrc 中,而不是每个脚本或函数都有一个文件。当脚本足够大时(就像现在?),我会把它移到一个单独的文件中。 我见过 Term::ANSIColor 被其他人使用。我猜它比使用转义字符更好?

以上是关于如何在 unicode 形式之间进行转换:字符串、名称、数字的主要内容,如果未能解决你的问题,请参考以下文章

UTF-8 表示和 unicode 表示之间的字符串转换

类型转换在本地PC和服务器环境之间更改

在Ruby中将unicode代码点转换为字符串字符

SSIS 包:在 unicode 和非 unicode 字符串数据类型之间转换

URL参数中汉字转换为16进制Unicode形式

如何判断一个字符串是不是是unicode编码?