在bash中按整数序数发出字符(或多字节二进制字符串)

时间:2016-12-14 01:58:14

标签: linux bash

我试图按原样在bash中回显整数,而不将每个数字转换为ASCII并输出相应的序列。 e.g。

echo "123" | hd
00000000  31 32 33 0a                                       |123.|

它输出每个字符的ASCII码。如何输出123本身,例如无符号整数?所以我得到像

这样的东西
00000000  0x7B 00 00 00

3 个答案:

答案 0 :(得分:2)

这是printf

的工作
$ printf "\x$(printf '%x' "123")" | hd
00000000  7b                                                |{|

内部printf将十进制数123转换为十六进制,外部printf使用\x创建一个具有该值的字节。

如果你想要几个字节,请使用:

$ printf '%b' "$(printf '\\x%x' "123" "96" "68")" | hd
00000000  7b 60 44                                          |{`D|

或者,如果你想使用十六进制:

$ printf '%b' "$(printf '\\x%x' "0x7f" "0xFF" "0xFF")" | hd
00000000  7f ff ff                                          |...|

或者,在这种情况下,简单地说:

$ printf '\x7f\xFF\xFF' | hd
00000000  7f ff ff                                          |...|

答案 1 :(得分:1)

你必须小心结束。 x86是little endian所以你必须先存储最低有效字节。

例如,如果要在磁盘上存储32位整数:2'937'252'660d = AF'12'EB'34h,则必须写入:0x34,然后是0xEB,然后是0x12,然后是0xAF,按此顺序。

使用此帮助程序的目的与您的目的相同:

printf "%.4x\n" 2937252660 | fold -b2 | tac | while read a; do echo -e -n "\\x${a}"; done

printf从dec base更改为hex base

fold按2个字符组分组,即1个字节

tac反转行(这是应用little-endian的地方)

while循环回显一个原始字节

答案 2 :(得分:0)

借用@Setop's answer的观察结果,示例暗示OP需要uint32s,但试图建立一个更有效的实现(不涉及子shell或外部命令):

print_byte() {
  local val
  printf -v val '%02x' "$1"
  printf '%b' "\x${val}"
}

print_uint32() {
  print_byte "$(( ( $1 / (( 256 ** 0 )) ) % 256 ))"
  print_byte "$(( ( $1 / (( 256 ** 1 )) ) % 256 ))"
  print_byte "$(( ( $1 / (( 256 ** 2 )) ) % 256 ))"
  print_byte "$(( ( $1 / (( 256 ** 3 )) ) % 256 ))"
}

因此:

print_uint32 32 | xxd # this should be a single space, padded with nulls

...正确收益:

00000000: 2000 0000                                ...

...正如Python struct.unpack()模块反转回原始值所证明的那样:

$ print_uint32 32 |
>   python -c 'import struct, sys; print struct.unpack("I", sys.stdin.read())'
32