我想使用以下命令输出所有 ascii 字符的字符串
for i in `seq 32 127`; do printf "%c" $i; done
上述命令的输出是:
33333334444444444555555555566666666667777777777..............
它是每个数字的第一个(从左起)数字。
浏览这个网站我发现了我的问题的答案如何在 CLI 中打印所有可打印的 ASCII 字符?,但是我仍然不明白为什么我的原始代码片段没有按预期输出 ascii 字符。
答案1
您不能使用printf "%c" $i
C 中的类似方法直接打印 ascii 代码。
你必须先将 i 的十进制值转换为其八进制值然后你必须使用 using 来打印它printf
,并将其放在\
各自的八进制值前面。
要打印A
,您必须将十进制 65 转换为八进制,即 101,然后必须将该八进制值打印为:
printf "\101\n"
这将打印A
.
所以你必须将其修改为:
for i in `seq 32 127`; do printf \\$(printf "%o" $i);done;
但是通过使用awk
你可以像C语言一样直接打印
awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
答案2
%c
将关联参数解释为 char:仅打印给定参数的第一个字符
您似乎已经有了一种打印它们的方法,但这是一种变体。
for i in `seq 32 127`; do printf "\x$(printf "%x" $i) $i"; done
答案3
你需要printf
,但只需要一次;您可以printf
用更简单、更高效的echo
Bash 转义序列来替换其中的一种用法:
对于十六进制:
for i in `seq 32 127`; do
echo -ne \\x$(printf %02x $i)
done
对于八进制:
for i in `seq 32 127`; do
echo -ne \\0$(printf %03o $i)
done
答案4
如果像我一样,您希望printf
尽可能保持格式字符串不变,请更改:
for i in `seq 32 127`; do printf "\\$(printf %o "$i")"; done
for i in `seq 32 127`; do printf "\x$(printf %x "$i")"; done # not POSIX
到
for i in `seq 32 127`; do printf %b "\0$(printf %o "$i")"; done
for i in `seq 32 127`; do printf %b "\x$(printf %x "$i")"; done # not POSIX
(顺便说一句,POSIX 标准printf
不包括\x
格式字符串中允许的转义序列。)
由于关注点分离,我更喜欢使printf
格式字符串尽可能保持不变。格式字符串关注的是格式化;参数适用于变化的数据。如果格式字符串中的扩展包含可以解释为格式说明符的内容,也可能会出现问题,如所讨论的这里在 C 编程环境中。此处还讨论了:ShellCheck linting 规则SC2059 不要在 printf 格式字符串中使用变量。