97

性格到价值的作品:

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

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

  • 我如何取 65 并将其变成 A?
  • \'A 使用 printf 将 ASCII 字符转换为其值。语法是特定printf还是在 BASH 中的其他任何地方使用?(这么小的字符串很难用谷歌搜索。)
4

13 回答 13

78

一条线

printf "\x$(printf %x 65)"

两条线

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

如果您不介意使用,这是一个awk

awk 'BEGIN{printf "%c", 65}'
于 2009-11-18T10:10:40.580 回答
39

这有效(使用八进制值):

$ 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
于 2015-09-22T23:16:10.490 回答
17

对于您的第二个问题,前导引号语法 ( ) 似乎\'A特定于printf

如果前导字符是单引号或双引号,则该值应是单引号或双引号后字符的基础代码集中的数值。

来自https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html

于 2011-12-01T09:43:53.000 回答
10

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

printf "\x41\n"
printf "\101\n"
于 2009-05-20T21:21:32.667 回答
8

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

perl -e 'printf "%c\n", 65;'
于 2009-05-20T21:12:31.887 回答
7

如果你想保存字符的 ASCII 值:(我在 BASH 中做了这个并且它有效)

{
char="A"

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

echo $testing}

输出:65

于 2012-02-21T22:49:58.120 回答
4

如果您转换65为十六进制,则为0x41

$ echo -e "\x41" A

于 2017-01-20T16:27:57.690 回答
4

对于大写字母:

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

输出:

C
于 2019-07-26T01:11:16.183 回答
3

这是将 65 转换为 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
于 2014-11-20T10:05:08.783 回答
2

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

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

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
于 2020-08-03T21:24:38.573 回答
0

以下脚本打印aaa...zzz(即aaa > aab > aac > ... > zzx > zzy > zzz

for i in $(seq 0 25); do FIRST=$(printf \\$(printf '%03o' $[97+$i]) | tr -d '\n'); for f in $(seq 0 25); do SECOND=$(printf \\$(printf '%03o' $[97+$f]) | tr -d '\n'); for g in $(seq 0 25); do THIRD=$(printf \\$(printf '%03o' $[97+$g]) | tr -d '\n'); echo "${FIRST}${SECOND}${THIRD}"; done; done; done
于 2021-03-18T17:15:50.967 回答
0

这是一个没有eval也没有$()也没有 `` 的解决方案:

ord () {
 local s
 printf -v s '\\%03o' $1
 printf "$s"
}

ord 65
于 2020-12-16T20:28:10.313 回答
0

鉴于没有那么多 1 字节字符,但只有 256 个,它们可以在脚本启动时快速预先计算:

declare -ag CHARS=()
for REPLY in {{0..9},{a..f}}{{0..9},{a..f}}; do
  printf -v CHARS[${#CHARS[@]}] "\x$REPLY"
done

(我重用了可丢弃REPLY变量,但您可以local在 init 中自己使用function

然后...

$ echo "${CHARS[65]}"
A
$ i=65
$ echo "${CHARS[i]}"
A

注意\x00,它的值在 Bash 中没有被正确处理,因为它是字符串终止符:

$ var=$'qwe\x00rty'
$ echo ${#var}
3
$ echo "<${var}>"
<qwe>

所以,"${CHAR[0]}"在 Bash 下永远是个问题。

这样,您可以避免每次需要处理一个字符时一次又一次地进行输出捕获、内联文本替换和重新解析;这对于通过或的子进程 IPCxxd来说更糟。awkperl

于 2021-11-16T03:05:24.720 回答