我有一个unicode点数组,我希望能够转换回字符并将其作为字符串存储在变量中。在下面的例子中,它只是"Hello World!"代码点数组,但我可以有任何unicode数字(最多16位)。
array=( 72 101 108 108 111 32 87 111 114 108 100 33 )
我检查了:
- 如何在*nix中使用控制台工具将uXXXX unicode转换为UTF-8
- 如何将字符串中的所有UTF8 Unicode字符转换为使用bash/shell/zsh的相关代码点?
和其他在线资源,但我仍然不知道如何做到这一点。我尝试了如下操作:
temp=
for c in ${array[@]}; do
temp+="U$c"
done
printf %b "$temp"
我还看到bash有一个新功能,允许您执行echo -e 'Uxxxxx'
或$'Uxxx'
,但在我的情况下,它不起作用,因为即使我迭代数组并将每个代码点存储在变量i
中,单引号会阻止bash在这种情况下扩展它:echo $'U$i'
,我甚至尝试了echo "$'U$i'"
。
我完全不知道如何用一种简单的方式用纯bash来做这件事。
让您感到困惑的是,您的数组中充满了编码点的十进制数字,但是U
符号采用十六进制数字。例如,数组中的第一个元素是"72"——在十进制中,这是"H"的代码,但在十六进制中,它相当于十进制114,这是" "的代码。
所以要使用U
表示法,首先需要将数字转换为十六进制,可以使用printf %x
:
for c in "${array[@]}"; do
temp+="\U$(printf %x "$c")" # Convert dec->hex, add U
done
printf %b "$temp" # Convert U<codepoint> to actual characters
正如dave_thompson_085在注释中指出的那样,您可以通过将整个数组转换为单个printf
:
printf %b "$(printf '\U%x' "${array[@]}")"
Shell脚本不是万能的。对于复杂的操作,它们通常依赖于linux安装中常见的其他实用程序。在这种情况下,iconv
可以提供帮助。
array=( 72 101 108 108 111 32 87 111 114 108 100 33 )
temp=
for c in ${array[@]}; do temp+=$(printf '\x%x' $c); done
temp=$(echo -ne $temp | iconv -f utf8)
printf %b "$temp"
为什么要调用数组array
,然后继续使用string
?
tmp=""
arr=( 72 101 108 108 111 32 87 111 114 108 100 33 )
for c in "${arr[@]}"; do tmp+="U$c"; done
printf %b "$tmp"