如何使用bash脚本读取二进制文件内容?

如何使用bash脚本读取二进制文件内容?

我想读取一个字符,然后读取固定长度的字符串(该字符串在文件中不是以空结尾,其长度由前面的字符给出)。

我怎样才能在 bash 脚本中做到这一点?如何定义字符串变量以便我可以对其进行一些后处理?

答案1

如果您想坚持使用 shell 实用程序,您可以使用head提取多个字节,并将od字节转换为数字。

export LC_ALL=C    # make sure we aren't in a multibyte locale
n=$(head -c 1 | od -An -t u1)
string=$(head -c $n)

然而,这不起作用对于二进制数据。有两个问题:

  • 命令替换$(…)最后的换行符在命令输出中。有一种相当简单的解决方法:确保输出以换行符以外的字符结尾,然后删除该字符。

    string=$(head -c $n; echo .); string=${string%.}
    
  • Bash 与大多数 shell 一样,不擅长处理空字节。从 bash 4.1 开始,空字节被简单地从命令替换的结果中删除。 Dash 0.5.5 和 pdksh 5.2 具有相同的行为,并且 ATT ksh 在第一个空字节处停止读取。一般来说,shell 及其实用程序不适合处理二进制文件。 (Zsh 是个例外,它被设计为支持空字节。)

如果您有二进制数据,您将需要切换到 Perl 或 Python 等语言。

<input_file perl -e '
  read STDIN, $c, 1 or die $!;    # read length byte
  $n = read STDIN, $s, ord($c);   # read data
  die $! if !defined $n;
  die "Input file too short" if ($n != ord($c));
  # Process $s here
'
<input_file python -c '
  import sys
  n = ord(sys.stdin.read(1))      # read length byte
  s = sys.stdin.read(n)           # read data
  if len(s) < n: raise ValueError("input file too short")
  # Process s here
'

答案2

如果您希望能够在 shell 中处理二进制文件,最好的选择(唯一?)是使用十六进制转储工具。

hexdump -v -e '/1 "%u\n"' binary.file | while read c; do
  echo $c
done

只读 X 字节:

head -cX binary.file | hexdump -v -e '/1 "%u\n"' | while read c; do
  echo $c
done

读取长度(并使用 0 作为长度),然后将“string”作为字节十进制值:

len=$(head -c1 binary.file | hexdump -v -e '/1 "%u\n"')
if [ $len -gt 0 ]; then
  tail -c+2 binary.file | head -c$len | hexdump -v -e '/1 "%u\n"' | while read c; do
    echo $c
  done
fi

答案3

exec 3<binary.file     # open the file for reading on file descriptor 3
IFS=                   #
read -N1 -u3 char      # read 1 character into variable "char"

# to obtain the ordinal value of the char "char"
num=$(printf %s "$char" | od -An -vtu1 | sed 's/^[[:space:]]*//')

read -N$num -u3 str    # read "num" chars
exec 3<&-              # close fd 3

答案4

这只是复制一个二进制文件:

 while read -n 1 byte ; do printf "%b" "$byte" ; done < "$input" > "$output"

相关内容