零的 ASCII 十六进制代码是 0x30。因此,您可以通过执行 来打印零printf '\x30'
,并且它将打印零。
如果将其放入名为 myScript.sh 的 shell 脚本中,然后执行./myScript.sh
,它也会打印一个零。
但如果您执行sh -c printf '\x30'
或sh myScript.sh
,您将得到文字字符“\x30”,而不是将其解释为单个字节。
这是为什么?
(已在多台机器上观察到行为,我相信所有这些机器都在运行 bash)。
答案1
printf
在某些 shell 中(bash
至少ksh
;zsh
甚至在sh
仿真模式下)的实现理解\xHH
为十六进制数HH
。然而,这是对标准printf
规格。
POSIX 标准要求的是printf
识别\ooo
,其中ooo
是一位、两位或三位数字八进制格式参数中的数字以及\0ooo
用于%b
格式指令的参数中的数字(以匹配echo
行为)。
/bin/sh
在您的系统上代表的 shell最有可能dash
(或者不太可能是yash
),与 一起使用时,它理解八进制(像所有标准 shell 一样),但不理解十六进制printf
。
十六进制数30换算成八进制是60,所以
$ sh -c 'printf "%b\n" "$1"' sh '\060'
0
或者,如果您不想将八进制数作为参数传递,而是想将其用作静态文字:
$ sh -c 'printf "\60\n"'
0
(请注意您的问题中的语句的区别sh -c
:整个语句(包括其参数)是作为实用程序选项的printf
选项参数给出的字符串的一部分。我假设您的问题中的内容是一个简单的拼写错误.)sh
-c
您的脚本成功打印字符的原因0
要么是因为您的#!
脚本中有一个 -line 指向bash
shell 可执行文件,要么您有不根本没有这样的行,而是从交互式 shell 运行脚本bash
。bash
当执行不带行的 shell 脚本时#!
,shell 将用来运行bash
它(请参阅哪个 shell 解释器运行不带 shebang 的脚本?有关此细节的更多信息)。
当您使用显式解释器运行脚本时(如 中所示),sh myScript.sh
该#!
行(如果有)将被忽略。
答案2
当我执行时
$ sh -c printf '\x30'
我明白了
printf: usage: printf [-v var] format [arguments]
它已经提供了一个宝贵的提示,但printf
没有获得预期的参数。解决方案是通过将命令参数括在引号中来确保命令参数是单个字符串,而不是多个参数。当然,添加换行符以提高可读性也没有什么坏处:
$ sh -c "printf '\x30\n'"
0