Ama*_*nda 16 bash text-processing binary
我想读取一个字符,然后是一个固定长度的字符串(该字符串在文件中不是空终止的,其长度由前面的字符给出)。
如何在 bash 脚本中执行此操作?如何定义字符串变量以便我可以对其进行一些后期处理?
Gil*_*il' 19
如果您想坚持使用 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)
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于二进制数据。有两个问题:
命令替换$(…)
条最终换行符在命令输出。有一个相当简单的解决方法:确保输出以换行符以外的字符结尾,然后删除该字符。
string=$(head -c $n; echo .); string=${string%.}
Run Code Online (Sandbox Code Playgroud)Bash 和大多数 shell 一样,不擅长处理null bytes。从 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
'
Run Code Online (Sandbox Code Playgroud)
<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
'
Run Code Online (Sandbox Code Playgroud)
如果您希望能够在 shell 中处理二进制文件,最好的选择(仅?)是使用hexdump工具。
hexdump -v -e '/1 "%u\n"' binary.file | while read c; do
echo $c
done
Run Code Online (Sandbox Code Playgroud)
只读 X 字节:
head -cX binary.file | hexdump -v -e '/1 "%u\n"' | while read c; do
echo $c
done
Run Code Online (Sandbox Code Playgroud)
读取长度(并使用 0 作为长度),然后将“字符串”作为字节十进制值:
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
Run Code Online (Sandbox Code Playgroud)