如何使用 Bash 编写二进制文件?

发布于 2024-10-30 20:33:58 字数 364 浏览 6 评论 0原文

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

我不能使用C、perl、其他脚本语言(目标是嵌入式设备)。我使用 awk 尝试了这一点,在桌面上它确实有效:

# awk  'BEGIN{ printf "%c%c%c%c", 48, 00, 49, 00 }' | hexdump
0000000 0030 0031                              
0000004

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

您有什么建议?

My problem is that I need to create a file with this exact bytes: 48, 00, 49, 00.

I cannot use C, perl, other scripting language (the target is an embedded device). I tried this using awk, and in desktop it does work:

# awk  'BEGIN{ printf "%c%c%c%c", 48, 00, 49, 00 }' | hexdump
0000000 0030 0031                              
0000004

However the target platform is running busybox v1.13.2 and this code does not work there. The awk version there does not output ascii "0" (all other values are ok).

What are your recommendations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

撩心不撩汉 2024-11-06 20:34:04

您可以使用以下命令:

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

you can use the following command:

echo -n -e \\x48\\x00\\x49\\x00 > myfile
ぺ禁宫浮华殁 2024-11-06 20:34:04

我需要在旧的 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

I needed to write binary files from hex using busybox within an old Android shell. This printf with a redirect worked in my use case.

Write the binary data in hex:

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

Display the result in hex:

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

Display the result in ascii:

# cat /sdcard/test.txt
test
情归归情 2024-11-06 20:34:04

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

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

you could try echo, that also allows arbitrary ascii chars (those numbers are octal numbers).

echo -n -e \\0060\\0000\\0061\\0000  | hexdump
£噩梦荏苒 2024-11-06 20:34:04

POSIX AWK 标准规定,以 %c 格式将 0 传递给 AWK 的 printf 可能会导致未指定的行为。然而...... 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

POSIX AWK standard says that passing a 0 to AWK's printf with %c format can result in unspecified behaviour. However... POSIX echo also is very limited, and though octal and hexadecimal specifiers (and -n) will work on GNU echo and BASH built-in... They may not work everywhere. To maximize the chance that you get consistent behaviour on all POSIX systems, it is better to use the shell command line's printf than either of these.

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

This looks odd to me though... You may be wanting to output 0x48, 0x00, 0x49, 0x00 -- which looks like a pretty pilot number in octal:

$ printf '\110\000\111\000' | od -An -tx1
 48 00 49 00
挥剑断情 2024-11-06 20:34:04

几个更通用的函数来输出整数:

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

A couple of more general functions to output integers:

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
}

Use to make an audio WAV file header for iio data stream:

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 data capture to WAV file:

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
盛夏已如深秋| 2024-11-06 20:34:04

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

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

这是输出:

$ printf "%c" 1 | hexdump
0000000 0031                    

I don't know what's in busybox, but this might work because printf is smaller than awk.

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

This is the output:

$ printf "%c" 1 | hexdump
0000000 0031                    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文