我提到的“printf”是标准“程序”(不是内置的):/usr/bin/printf
我正在测试 printf out 作为一种可行的方法,将 Unicode Codepoint Hex 文字转换为其 Unicoder 字符表示形式,
我看起来很好,似乎完美无缺......(顺便说一句,内置的 printf 根本不能做到这一点(我认为)......
然后我想在代码频谱的最低端进行测试,但结果失败了,出现了大量错误。所有错误都在 ASCII 范围内(= 7 位)
最奇怪的是,3个值正常打印;它们是:
- $ \u0024
- @ \u0040
- ` \u0060
我想知道这里发生了什么。 ASCII 字符集绝对是 Unicode 码点序列的一部分……
我很困惑,仍然没有一个好的方法来编写这个特殊的转换脚本。欢迎提出建议。
要解决同样的大量错误,请将以下代码粘贴到终端...
# Here is one of the error messages
# /usr/bin/printf: invalid universal character name \u0041
# ...for them all, run the following script
(
for nib1 in {0..9} {A..F}; do
for nib0 in {0..9} {A..F}; do
[[ $nib1 < A ]] && nl="\n" || nl=" "
$(type -P printf) "\u00$nib1$nib0$nl"
done
done
echo
)
答案1
三个工作字符是三个可打印的 ASCII 字符,它们不在C基本字符集。在 C 中禁止使用这些字符的原因是,这会给编译器带来困难:它们需要\u
在词法分析之前执行插值,我认为这会在某些极端情况下出现问题,而且在许多编译器中也不切实际(因为基本字符集之外的字符只需要在少数地方允许使用)。
在 shell 实用程序中,使用相同的禁用字符是没有意义的。我怀疑这是一个错误,并且$
,@
并且`
应该起作用。不支持它们的原因再次是为了使解析字符串变得更容易。例如,如果你想确定没有要在数据库查询中输入的字符串中的特殊字符,您可以检查字符串不包含'
,而不必担心它包含\u002a
。
考虑使用重新编码就像GNU coreutils 手册,或者(实际上更具可移植性)Perl 或 python。
答案2
printf 命令不接受此范围内的字符是有原因的。如果您查看 printf 的源代码,您将看到以下注释:
通用字符名称不得指定 00000000 至 00000020、0000007F 至 0000009F 或 0000D800 至 0000DFFF(含)范围内的字符短标识符。通用字符名称不得指定所需字符集中的字符。
你可能无需进行该检查即可重新编译,但我认为这是非常刻意的。尝试使用不带 \u 的命令,例如:
(
for nib1 in {0..9} {A..F}; do
for nib0 in {0..9} {A..F}; do
$(type -P printf) "\00$nib1$nib0"
done
done
echo
)
答案3
(for nib1 in {0..9} {A..F}; do
for nib0 in {0..9} {A..F}; do
$(type -P printf) "\x$nib1$nib0"
done
done
echo )
打印件(手工调整格式)
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
� � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
请注意,一些“字符”控制代码“起作用”,即 HT、VT、LF 等。