在BASH中使用printf将整数ASCII值转换为字符

109

角色转值有效:

$ printf "%d\n" \'A
65
$ 

我有两个问题,第一个问题最重要:

  • 如何将65转换为A?
  • 'A使用printf将ASCII字符转换为其值。 该语法是否特定于 printf,还是在BASH的其他地方也使用?(这样的小字符串很难在Google中搜索)

在Windows中,使用ALT+65来打印ASCII字符 - 不幸的是,在Unix/bash中无法使用该方法 ;) - schnaader
3
@schnaader 但你无法编写脚本来实现那个。 - ctrl-alt-delor
3
@richard: 嗯... 这不是一件容易或实际的事情,但你可以尝试 :) 只需启动运行Windows或MS-DOS的虚拟机,将"echo ", ALT, 6, 5, ">mysharedfolder\file.txt"发送为按键,然后从虚拟机共享文件夹中读取file.txt即可。 - schnaader
2
@schnaader 你能用Wine来做吗? - emory
巔峰亂發帖 - undefined
13个回答

86

一行

printf "\x$(printf %x 65)"
两行
set $(printf %x 65)
printf "\x$1"

如果您不介意使用 awk,这里有一个示例:

awk 'BEGIN{printf "%c", 65}'

4
可以这样写:printf "$(printf '\\x%02x' $char)" - 0andriy

49

这个可以正常工作(使用八进制的值):

$ printf '%b' '\101'
A

即使对于某些(不超过 7 个)序列:

$ printf '%b' '\'{101..107}
ABCDEFG

一种允许任何范围的(十进制)值的通用结构是:

$ printf '%b' $(printf '\\%03o' {65..122})
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz

或者您可以使用字符的十六进制值:

$ printf '%b' $(printf '\\x%x' {65..122})
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz

您还可以使用 xxd(使用十六进制值)获取字符的值:
$ echo "41" | xxd -p -r
A

也就是说,一个操作是另一个操作的相反。

$ printf "%x" "'A" | xxd -p -r
A

同时也可以处理多个十六进制值:

$ echo "41 42 43 44 45 46 47 48 49 4a" | xxd -p -r
ABCDEFGHIJ

或序列(此处使用printf获取十六进制值):

$ printf '%x' {65..90} | xxd -r -p 
ABCDEFGHIJKLMNOPQRSTUVWXYZ

甚至可以使用awk:


$ echo 65 | awk '{printf("%c",$1)}'
A

即使是对于序列:

$ seq 65 90 | awk '{printf("%c",$1)}'
ABCDEFGHIJKLMNOPQRSTUVWXYZ

最终的示例甚至可以扩展为创建动态生成的ASCII表格: seq 98 102 | awk 'BEGIN{print "\n\tDEC\tOCT\tHEX\t字符\n\t---\t---\t--\t-"}; {printf("\t%d\t%o\t%x\t%c\n",$1,$1,$1,$1)}; END{printf "\n"}'{感谢此答案另一个问题} - Jim Grisham

20

13

一种选项是直接使用十六进制或八进制表示法输入您感兴趣的字符:

printf "\x41\n"
printf "\101\n"

如果我们的键盘上没有%字符,也能正常工作的解决方案+1 :D 我正在使用Nokia N900上的postmarketOS Linux终端,并希望将其打印出来以便在命令中复制粘贴 :) - baptx
我需要在bash脚本中测试一个字符是否为回车符(\r),我发现我必须使用以下内容:testchar=$'\r'; if [ ${testchar} = $'\r' ]; then echo "is true"; else echo "is false"; fi。可以使用ASCII十六进制代替\r,即$'\x0D'。但是,条件语句中的字符串“\r”或其十六进制等效物均无法正常工作,始终返回false。 - Stephen Hosking
我在printf手册中找不到\x。这个在哪里有记录?谢谢。 - nortally

9

对于这种转换,我使用perl:

perl -e 'printf "%c\n", 65;'

4
或者在Perl中,打印chr(65),"\n"。如果你需要频繁地这样做,Perl可能是一个不错的选择,但使用Shell的printf将数字转换为可以放入\0转义序列的内容也完全可以。使用Unicode更复杂,因为需要在printf中使用\u支持。 - Peter Cordes
1
不幸的是,Perl成为了被遗忘的语言。现在几乎每台Linux机器都有更好的Python可用。此外,问题是关于Shell-Bash而不是其他平台! - s3n0

9
如果您想保存字符的ASCII值: (我在BASH中做到了这一点,并且它有效)
{
char="A"

testing=$( printf "%d" "'${char}" )

echo $testing}

输出: 65


这个可行,谢谢。我想从输入的字符中获取一个整数(ASCII码)。我写了一个脚本:{read -n 1 c; echo $( printf "%d" "'${c}" )} - Phaedrus

6
如果你把数字65转换成十六进制,它会变成0x41$ echo -e "\x41" A

如果您知道要打印的ASCII字符的十六进制值,则可以使用“$ printf“\x41”命令。 - katta

6

大写字母:

i=67
letters=({A..Z})
echo "${letters[$i-65]}"

输出:

C

4

这里是将65转化为16进制A的另一种方式(通过八进制):

help printf  # in Bash
man bash | less -Ip '^[[:blank:]]*printf'

printf "%d\n" '"A'
printf "%d\n" "'A"

printf '%b\n' "$(printf '\%03o' 65)"

要在man bash中搜索\',可以使用以下命令(尽管在这种情况下是徒劳的):

man bash | less -Ip "\\\'"  # press <n> to go through the matches

感谢您提供的manpage解析示例! - Jim Grisham

2

这将打印出您的基本bash设置中的所有“可打印”字符:

printf '%b\n' $(printf '\\%03o' {30..127})

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接