在shell中编写二进制文件(shell,awk)

时间:2011-04-07 14:33:34

标签: bash awk busybox

我的问题是我需要创建一个具有这个确切字节的文件:48,00,49,00

我不能使用C(因为我无法部署任何内容,没有perl,没有其他脚本语言。我使用awk尝试过这种方法,而在桌面上它确实有效:

diego@diego-linux:~# awk  'BEGIN{ printf "%c%c%c%c", 48, 00, 49, 00 }' | hexdump
0000000 0030 0031                              
0000004

但是目标平台正在运行busybox v1.13.2,并且此代码在此处不起作用。那里的awk版本没有输出ascii“0”(所有其他值都没问题。)

你有什么建议?

6 个答案:

答案 0 :(得分:26)

您可以使用以下命令:

echo -n -e \\x48\\x00\\x49\\x00 > myfile

答案 1 :(得分:6)

POSIX AWK标准规定,将%0传递给AWK的printf并使用%c格式会导致未指定的行为。但是... POSIX echo也非常有限,虽然八进制和十六进制说明符(和-n)可以在GNU echo和BASH内置工作......它们可能无法在任何地方工作。为了最大限度地提高在所有POSIX系统上获得一致行为的可能性,最好使用shell命令行的printf而不是其中任何一个。

$ printf '\060\000\061\000' | od -An -tx1
 30 00 31 00

虽然这对我来说很奇怪......你可能想要输出0x48,0x00,0x49,0x00--这看起来像八进制中的漂亮导频数字:

$ printf '\110\000\111\000' | od -An -tx1
 48 00 49 00

答案 2 :(得分:5)

你可以尝试回声,这也允许任意的ascii字符(这些数字是八进制数字)。

echo -n -e \\0060\\0000\\0061\\0000  | hexdump

答案 3 :(得分:4)

我需要在旧的Android shell中使用busybox从十六进制中编写二进制文件。这个带有重定向的printf在我的用例中有效。

以十六进制编写二进制数据:

# busybox printf '\x74\x65\x73\x74' > /sdcard/test.txt

以十六进制显示结果:

# busybox hexdump -C /sdcard/test.txt
00000000  74 65 73 74                                       |test|
00000004

在ascii中显示结果:

# cat /sdcard/test.txt
test

答案 4 :(得分:1)

我不知道busybox中有什么,但这可能有效,因为printf小于awk。

$ printf "%c%c%c%c" 48 0 49 0 | hexdump

这是输出:

$ printf "%c" 1 | hexdump
0000000 0031                    

答案 5 :(得分:1)

一些用于输出整数的通用函数:

le16 () { # little endian 16 bit binary output 1st param: integer to 2nd param: file 
  v=`awk -v n=$1 'BEGIN{printf "%04X", n;}'`
  echo -n -e "\\x${v:2:2}\\x${v:0:2}" >> $2
}

le32 () { # 32 bit version
  v=`awk -v n=$1 'BEGIN{printf "%08X", n;}'`
  echo -n -e "\\x${v:6:2}\\x${v:4:2}\\x${v:2:2}\\x${v:0:2}" >> $2
}

用于为iio数据流制作音频WAV文件头:

channels=2
bits_per_sample=16
let "block_align = channels * bits_per_sample / 8"    

wave_header () { # pass file name and data size as parameters; rest are constants set elsewhere
  data_size=$2
  let "RIFFsize = data_size + 44 - 8"
  let "bytes_per_sec = sampleHz * block_align"

  echo -e -n "RIFF" > $1
    le32 $RIFFsize $1
  echo -e -n "WAVEfmt " >> $1
    le32 16 $1  # format size
    le16 1 $1   #format tag: 1 = PCM
    le16 $channels $1
    le32 $sampleHz $1
    le32 $bytes_per_sec $1
    le16 $block_align $1
    le16 $bits_per_sample $1   # bits per sample
  echo -e -n "data" >> $1
    le32 $data_size $1
}

Linux iio ADC数据捕获到WAV文件:

sampleHz=8000
milliseconds=15  # capture length 

cd /sys/bus/iio/devices/iio:device0

cat /sys/bus/iio/devices/trigger0/name > trigger/current_trigger

echo 0 > buffer/enable

echo 0 > scan_elements/in_voltage0_en  #
echo 1 > scan_elements/in_voltage1_en  #  
echo 1 > scan_elements/in_voltage2_en  # 
echo 0 > scan_elements/in_voltage3_en  #

echo $sampleHz > sampling_frequency
sampleHz=`cat sampling_frequency`  # read back actual sample rate

let "buffer_length = block_align * sampleHz * milliseconds / 1000"
echo $buffer_length > buffer/length

cd $HOME

echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable
wave_header data.wav $buffer_length
head -c $buffer_length /dev/iio:device0 >> data.wav  # LE16 data
echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable