author: hjjdebug
date: 2025年 01月 05日 星期日 16:14:41 CST
description: 用shell把(1到100)100個整數寫入到二進制文件
1. 問題分析(需求分析)
在c語言下, 整數int 是按4個字節存儲的,能表示最大0xffffffff的范圍
但shell并沒有一條命令能夠實現把一個整數寫入二進制文件.
所以需要我們實現一個函數,叫writeint(), 它接收一個參數, 作用是把參數
當成一個整數按4byte寫入到二進制文件.
這樣我們只要做一個循環, 依次調用這個函數并傳入參數1-100即可.
for i in {1…100}
do
writeint $i
done
2. writeint() 的實現
方法1: 利用echo -ne 命令, 其中n 是不要追加換行符, e是支持轉義功能
echo -ne “\x12” 會把16進制 0x12 輸出到屏幕.
可惜 echo -ne 只能輸出一個byte的16進制數據,要想輸出多個字節只能循環輸出.
所以我們可以把數據與0xff相與,再轉成16進制,輸出一個byte.
再處理輸出2,3,4bytes. 其核心部分是
echo -ne "\x$(printf “%02x” $var)
具體實現可參考下面代碼
方法2: 利用xxd -r -g0 命令來實現從可顯示16進制到二進制的轉換.
-r 是reverse逆向轉換
-g0 是指定格式是光禿禿的16進制格式
不過要想利用這個命令,還要先構建所要求的格式,格式都是可打印字符串,就比較好辦了.
首先用printf “0: %08x” $var, 把整數按一定格式輸出. 包含4bytes 16進制數據
其中"0: "是格式所要求的, 代表的是數據所處的位置.
而后用sed 命令把16進制數據重新調整次序為little endian 格式
然后用xxd -r -g0輸出二進制數據.這有可能是不可打印的字符(二進制本來也不想在屏幕上輸出,需要重定向到文件.)
3. 參考源碼如下:
#!/bin/bash# 利用echo 命令實現, 但echo 每次只能寫1byte 二進制數據.
# int 變量按c 標準是一個占4bytes 的變量
# 具體實現如下
# 1. 利用與運算取出字節
# 2. 利用echo -ne 將一個字節按二進制寫入到二進制文件
# 3. 循環4次
writeint()
{local i varfor((i=0;i<4;i++))dolet var=$((($1>>($i*8))&0xff)) # $(()) 完成運算echo -ne "\x$(printf "%02x" $var)" # echo 只能寫一個byte 二進制數據done
}# writeint 的另一種實現, 利用xxd -r -g0 命令.
# xxd 命令是一個強大的命令,可以把一個二進制文件轉換為16進制來顯示.
# 也可以把一個16進制可打印的文件反方向轉換成一個二進制文件.
# 這里就是要用它的反向轉換-r, 按group0 的格式, 把組織好的16進制文件
# 變成一個4字節的二進制數據來輸出.
# xxd 是一個能將整個二進制文件進行轉換的命令, 這里只是構建了一個轉出4byte的文件
# 具體實現如下: 參考了網絡.
# 1. 用printf 將整數數據轉換為16進制,
# 2. 利用sed 實現數位的交換,把數據按格式組織好
# 3. 利用xxd -r -g0 將格式轉換為二進制存儲.
writeint2()
{printf "0: %.8x" $1 | sed -E 's/0: (..)(..)(..)(..)/0: \4\3\2\1/'|xxd -r -g0
}for i in {1..100}
do
writeint $i
#writeint2 $i
done
4. 執行效率測試
用time 命令實測了一下,
原以為wirteint2 效率會比較低,因為它即調用sed又調用xxd. 實測耗時并不多.
$ time ./write_int.sh > 1.bin
real 0m0.179s real 能小于user, 是多核的結果
user 0m0.234s
sys 0m0.080s
用writeint 來測試,
time ./write_int.sh > 1.bin
real 0m0.289s
user 0m0.232s
sys 0m0.084s
用writeint 函數,也許它的算術運算效率并不高,而且時間real一定會比user 大,反而比不過writeint2
writeint2 函數即調用sed又調用xxd, 竟然最終實際用時還比較小.
2種解決問題的方式,都有其妙處!
5. 補充知識點
用set 命令可查看所有變量和函數
用declare -F 可查看所有函數定義
用declare -f 可查看函數定義和內容
help declare 讓你了解更多declare的用法