初歩のシェルスクリプトで遊ぶ[8進数を2進数に変換(不真面目)]

調べものには使えません。
Ubuntu18.04(Virtualbox6.1.2) dash,bash

8進数を2進数に変換

000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
..............

↑こういう大量の、1バイトの8進数の列を、シェルスクリプトで2進数に変換するにはどうしたらいいんだろうか、という話。あくまで不真面目に。
たぶん模範解答的には、こんな感じだろう、とは思うけど。

tr "\n" " " | tr -s " " | sed 's/ / ;/g' | fold -s -w 1000 |
     xargs -I @@ echo 'obase=2;ibase=8;@@' | bc | fmt

私がやりたいのは、これじゃない。


手計算と同じように
#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'
8進数を2進数に変換する。
桁数ごとにcaseで2進数に入れ替えて並べる。

入力は、0詰め3桁の8進数、000〜377まで、のみ。

▼処理
紙とペンで計算するのと同じように実装。

1) 1行ごとに分けて[while read]
2) 1つずつに分けて[for]
3) 1桁ごとに空白を入れて[sed]
4) 1桁ごとに空白で分けて[set]
5) 1桁ごとに2進数に変換して
6) つなげてひとつの2進数に仕上げる

▼ 遅い理由
set `echo ${octal} | sed 's/\(.\)/\1\ /g'`

コマンド置換そのものと、ループごとにsedしていること。
sedをwhile-readの外に出すと、かなり早くなる。
echoも不要になるのでコマンド置換を無くすと、そこそこ早くなる。


$ time cat octalx256.txt | dash ./octToBin_01.sh 1>/dev/null
real	1m48.888s
user	1m31.792s
sys	0m20.426s
(108x16=1728[秒]) 111倍


#--------------------------------------------------------------comment
octToBin_01(){
( while read line ;do

for octal in ${line} ;do

set `echo ${octal} | sed 's/\(.\)/\1\ /g'`

case ${1} in 
( 0 )	bin76="00" ;;
( 1 )	bin76="01" ;;
( 2 )	bin76="10" ;;
( 3 )	bin76="11" ;;
esac
case ${2} in 
( 0 )	bin543="000" ;;
( 1 )	bin543="001" ;;
( 2 )	bin543="010" ;;
( 3 )	bin543="011" ;;
( 4 )	bin543="100" ;;
( 5 )	bin543="101" ;;
( 6 )	bin543="110" ;;
( 7 )	bin543="111" ;;
esac
case ${3} in 
( 0 )	bin210="000" ;;
( 1 )	bin210="001" ;;
( 2 )	bin210="010" ;;
( 3 )	bin210="011" ;;
( 4 )	bin210="100" ;;
( 5 )	bin210="101" ;;
( 6 )	bin210="110" ;;
( 7 )	bin210="111" ;;
esac

lineOut="${lineOut}${bin76}${bin543}${bin210} "
binOutCount="${binOutCount}@"

if test "0${binOutCount}" = "0@@@@@@@@" ;then
echo "${lineOut}"
binOutCount="" ;lineOut=""
fi

done ;done

if test -n "${lineOut}" ;then
echo "${lineOut}"
fi
)
}
: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377
111" |
#--------------------------------------------------------------test
octToBin_01
exit 0
sedをループの外に出して早くする

このくらいなら、まぁ納得。
000~377の連番を、4096回繰り返し、って意味です。入力のテキストファイルは。

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'
8進数を2進数に変換する。
桁数ごとにcaseで2進数に入れ替えて並べる。

入力は、0詰め3桁の8進数、000〜377まで、のみ。


$ time cat octalx4096.txt | dash ./octToBin_02.sh 1>/dev/null
real	0m15.454s
user	0m12.989s
sys	0m5.562s
(15.5[秒]) ←基準とする

$ time cat octalx4096.txt | bash ./octToBin_02.sh 1>/dev/null
real	1m1.505s
user	0m57.500s
sys	0m6.729s
#--------------------------------------------------------------comment


octToBin_02(){
sed "s/ /,/g;s/\([^,]\)/\1 /g" |
( while read line ;do
IFSBAK="$IFS"
IFS=, 
for octal in  ${line} ;do
IFS="$IFSBAK"
set ${octal}

case ${1} in 
( 0 )	bin76="00" ;;
( 1 )	bin76="01" ;;
( 2 )	bin76="10" ;;
( 3 )	bin76="11" ;;
esac
case ${2} in 
( 0 )	bin543="000" ;;
( 1 )	bin543="001" ;;
( 2 )	bin543="010" ;;
( 3 )	bin543="011" ;;
( 4 )	bin543="100" ;;
( 5 )	bin543="101" ;;
( 6 )	bin543="110" ;;
( 7 )	bin543="111" ;;
esac
case ${3} in 
( 0 )	bin210="000" ;;
( 1 )	bin210="001" ;;
( 2 )	bin210="010" ;;
( 3 )	bin210="011" ;;
( 4 )	bin210="100" ;;
( 5 )	bin210="101" ;;
( 6 )	bin210="110" ;;
( 7 )	bin210="111" ;;
esac

lineOut="${lineOut}${bin76}${bin543}${bin210} "
binOutCount="${binOutCount}@"

if test "0${binOutCount}" = "0@@@@@@@@" ;then
echo "${lineOut}"
binOutCount="" ;lineOut=""
fi

done ;done

if test -n "${lineOut}" ;then
echo "${lineOut}"
fi
)
}
: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377
111" |
#--------------------------------------------------------------test
octToBin_02
exit 0
桁数が多くてもなんとか

3桁固定でないやつを、文字並べと算術式とexprで。
expr、700倍も時間かかるのは、きっついなぁ。

#!/bin/dash
#set -x
: << '#--------------------------------------------------------------comment'
■8進数を2進数に変換する。【そこそこ汎用】

▼特徴
入力に「000〜377のみ」の制限がない版。
ひと桁ごとに変換して繋げる。計算というより、文字並べだ。

出力は3桁の整数倍。つまり8ビットだけ欲しくても、数字が9個並ぶ。

計算方法が3種類あり、これらのうち一つだけを有効にする。

▼入力
8進数のみ。半角空白か、改行で区切り。
8進数の桁数は、多少多くても問題ない。端末に表示できるなら。

▼processA
case文で入れ替え。桁ごと丸暗記方式。
$ time cat octalx4096.txt | dash ./octToBin_03.sh 1>/dev/null
real	1m34.181s
user	0m39.302s
sys	0m57.475s
(94[秒]) 6倍

▼processB
算術式で計算。
$ time cat octalx4096.txt | dash ./octToBin_03.sh 1>/dev/null
real	1m47.800s
user	0m54.139s
sys	0m57.461s
(107[秒]) 6.9倍

▼processC
exprコマンドを呼び出して計算。
(入力データが64分の1の量でテスト)
$ time cat octalx064.txt | dash ./octToBin_03.sh 1>/dev/null
real	2m47.168s
user	2m7.674s
sys	0m35.852s
(167x64=10688[秒]) 689倍

#--------------------------------------------------------------comment



octToBin_03(){
tr "\n" " " | tr --squeeze-repeats " " | tr " " "\n" |sed -e "s/[0-7]/& /g" |
while read octal ;do
for octDigit in  ${octal} ;do


#: << '#--------------------------------------------------------------processA'
case ${octDigit} in 
( 0 )	binDigit="000" ;;
( 1 )	binDigit="001" ;;
( 2 )	binDigit="010" ;;
( 3 )	binDigit="011" ;;
( 4 )	binDigit="100" ;;
( 5 )	binDigit="101" ;;
( 6 )	binDigit="110" ;;
( 7 )	binDigit="111" ;;
esac
binOut="${binOut}${binDigit}"
#--------------------------------------------------------------processA

: << '#--------------------------------------------------------------processB'
bin2=$((octDigit/4))
bin1=$(($((octDigit%4))/2))
bin0=$((octDigit%2))
binOut="${binOut}${bin2}${bin1}${bin0}"
#--------------------------------------------------------------processB

: << '#--------------------------------------------------------------processC'
bin2=`expr ${octDigit} / 4`
bin1=$(expr $(expr ${octDigit} % 4 ) / 2 )
bin0=`expr ${octDigit} % 2`
binOut="${binOut}${bin2}${bin1}${bin0}"
#--------------------------------------------------------------processC

done ;
echo -n "${binOut} "
binOut=""

done | fold --width=80 --spaces ;echo

}

: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377 
111 777" |
#--------------------------------------------------------------test

octToBin_03

exit 0
人間でもできなくはない

while-readは遅いとか、ループそのものがいけないとか聞いたけど、xargsといい勝負してるじゃないか。

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'
8進数を2進数に変換する。入力は、0詰め3桁の8進数、000〜377まで、のみ。

▼処理
丸暗記の中の丸暗記。

$ time cat octalx4096.txt | dash ./octToBin_04.sh >/dev/null
real	0m9.794s
user	0m6.795s
sys	0m2.979s 0.64倍

$ time cat octalx4096.txt | bash ./octToBin_04.sh >/dev/null
real	0m51.869s
user	0m47.995s
sys	0m3.785s

#--------------------------------------------------------------comment
octToBin_04(){
IoctObin000="00000000" ;IoctObin001="00000001" ;IoctObin002="00000010" ;IoctObin003="00000011" ;
IoctObin004="00000100" ;IoctObin005="00000101" ;IoctObin006="00000110" ;IoctObin007="00000111" ;
IoctObin010="00001000" ;IoctObin011="00001001" ;IoctObin012="00001010" ;IoctObin013="00001011" ;
IoctObin014="00001100" ;IoctObin015="00001101" ;IoctObin016="00001110" ;IoctObin017="00001111" ;
IoctObin020="00010000" ;IoctObin021="00010001" ;IoctObin022="00010010" ;IoctObin023="00010011" ;
IoctObin024="00010100" ;IoctObin025="00010101" ;IoctObin026="00010110" ;IoctObin027="00010111" ;
IoctObin030="00011000" ;IoctObin031="00011001" ;IoctObin032="00011010" ;IoctObin033="00011011" ;
IoctObin034="00011100" ;IoctObin035="00011101" ;IoctObin036="00011110" ;IoctObin037="00011111" ;
IoctObin040="00100000" ;IoctObin041="00100001" ;IoctObin042="00100010" ;IoctObin043="00100011" ;
IoctObin044="00100100" ;IoctObin045="00100101" ;IoctObin046="00100110" ;IoctObin047="00100111" ;
IoctObin050="00101000" ;IoctObin051="00101001" ;IoctObin052="00101010" ;IoctObin053="00101011" ;
IoctObin054="00101100" ;IoctObin055="00101101" ;IoctObin056="00101110" ;IoctObin057="00101111" ;
IoctObin060="00110000" ;IoctObin061="00110001" ;IoctObin062="00110010" ;IoctObin063="00110011" ;
IoctObin064="00110100" ;IoctObin065="00110101" ;IoctObin066="00110110" ;IoctObin067="00110111" ;
IoctObin070="00111000" ;IoctObin071="00111001" ;IoctObin072="00111010" ;IoctObin073="00111011" ;
IoctObin074="00111100" ;IoctObin075="00111101" ;IoctObin076="00111110" ;IoctObin077="00111111" ;
IoctObin100="01000000" ;IoctObin101="01000001" ;IoctObin102="01000010" ;IoctObin103="01000011" ;
IoctObin104="01000100" ;IoctObin105="01000101" ;IoctObin106="01000110" ;IoctObin107="01000111" ;
IoctObin110="01001000" ;IoctObin111="01001001" ;IoctObin112="01001010" ;IoctObin113="01001011" ;
IoctObin114="01001100" ;IoctObin115="01001101" ;IoctObin116="01001110" ;IoctObin117="01001111" ;
IoctObin120="01010000" ;IoctObin121="01010001" ;IoctObin122="01010010" ;IoctObin123="01010011" ;
IoctObin124="01010100" ;IoctObin125="01010101" ;IoctObin126="01010110" ;IoctObin127="01010111" ;
IoctObin130="01011000" ;IoctObin131="01011001" ;IoctObin132="01011010" ;IoctObin133="01011011" ;
IoctObin134="01011100" ;IoctObin135="01011101" ;IoctObin136="01011110" ;IoctObin137="01011111" ;
IoctObin140="01100000" ;IoctObin141="01100001" ;IoctObin142="01100010" ;IoctObin143="01100011" ;
IoctObin144="01100100" ;IoctObin145="01100101" ;IoctObin146="01100110" ;IoctObin147="01100111" ;
IoctObin150="01101000" ;IoctObin151="01101001" ;IoctObin152="01101010" ;IoctObin153="01101011" ;
IoctObin154="01101100" ;IoctObin155="01101101" ;IoctObin156="01101110" ;IoctObin157="01101111" ;
IoctObin160="01110000" ;IoctObin161="01110001" ;IoctObin162="01110010" ;IoctObin163="01110011" ;
IoctObin164="01110100" ;IoctObin165="01110101" ;IoctObin166="01110110" ;IoctObin167="01110111" ;
IoctObin170="01111000" ;IoctObin171="01111001" ;IoctObin172="01111010" ;IoctObin173="01111011" ;
IoctObin174="01111100" ;IoctObin175="01111101" ;IoctObin176="01111110" ;IoctObin177="01111111" ;
IoctObin200="10000000" ;IoctObin201="10000001" ;IoctObin202="10000010" ;IoctObin203="10000011" ;
IoctObin204="10000100" ;IoctObin205="10000101" ;IoctObin206="10000110" ;IoctObin207="10000111" ;
IoctObin210="10001000" ;IoctObin211="10001001" ;IoctObin212="10001010" ;IoctObin213="10001011" ;
IoctObin214="10001100" ;IoctObin215="10001101" ;IoctObin216="10001110" ;IoctObin217="10001111" ;
IoctObin220="10010000" ;IoctObin221="10010001" ;IoctObin222="10010010" ;IoctObin223="10010011" ;
IoctObin224="10010100" ;IoctObin225="10010101" ;IoctObin226="10010110" ;IoctObin227="10010111" ;
IoctObin230="10011000" ;IoctObin231="10011001" ;IoctObin232="10011010" ;IoctObin233="10011011" ;
IoctObin234="10011100" ;IoctObin235="10011101" ;IoctObin236="10011110" ;IoctObin237="10011111" ;
IoctObin240="10100000" ;IoctObin241="10100001" ;IoctObin242="10100010" ;IoctObin243="10100011" ;
IoctObin244="10100100" ;IoctObin245="10100101" ;IoctObin246="10100110" ;IoctObin247="10100111" ;
IoctObin250="10101000" ;IoctObin251="10101001" ;IoctObin252="10101010" ;IoctObin253="10101011" ;
IoctObin254="10101100" ;IoctObin255="10101101" ;IoctObin256="10101110" ;IoctObin257="10101111" ;
IoctObin260="10110000" ;IoctObin261="10110001" ;IoctObin262="10110010" ;IoctObin263="10110011" ;
IoctObin264="10110100" ;IoctObin265="10110101" ;IoctObin266="10110110" ;IoctObin267="10110111" ;
IoctObin270="10111000" ;IoctObin271="10111001" ;IoctObin272="10111010" ;IoctObin273="10111011" ;
IoctObin274="10111100" ;IoctObin275="10111101" ;IoctObin276="10111110" ;IoctObin277="10111111" ;
IoctObin300="11000000" ;IoctObin301="11000001" ;IoctObin302="11000010" ;IoctObin303="11000011" ;
IoctObin304="11000100" ;IoctObin305="11000101" ;IoctObin306="11000110" ;IoctObin307="11000111" ;
IoctObin310="11001000" ;IoctObin311="11001001" ;IoctObin312="11001010" ;IoctObin313="11001011" ;
IoctObin314="11001100" ;IoctObin315="11001101" ;IoctObin316="11001110" ;IoctObin317="11001111" ;
IoctObin320="11010000" ;IoctObin321="11010001" ;IoctObin322="11010010" ;IoctObin323="11010011" ;
IoctObin324="11010100" ;IoctObin325="11010101" ;IoctObin326="11010110" ;IoctObin327="11010111" ;
IoctObin330="11011000" ;IoctObin331="11011001" ;IoctObin332="11011010" ;IoctObin333="11011011" ;
IoctObin334="11011100" ;IoctObin335="11011101" ;IoctObin336="11011110" ;IoctObin337="11011111" ;
IoctObin340="11100000" ;IoctObin341="11100001" ;IoctObin342="11100010" ;IoctObin343="11100011" ;
IoctObin344="11100100" ;IoctObin345="11100101" ;IoctObin346="11100110" ;IoctObin347="11100111" ;
IoctObin350="11101000" ;IoctObin351="11101001" ;IoctObin352="11101010" ;IoctObin353="11101011" ;
IoctObin354="11101100" ;IoctObin355="11101101" ;IoctObin356="11101110" ;IoctObin357="11101111" ;
IoctObin360="11110000" ;IoctObin361="11110001" ;IoctObin362="11110010" ;IoctObin363="11110011" ;
IoctObin364="11110100" ;IoctObin365="11110101" ;IoctObin366="11110110" ;IoctObin367="11110111" ;
IoctObin370="11111000" ;IoctObin371="11111001" ;IoctObin372="11111010" ;IoctObin373="11111011" ;
IoctObin374="11111100" ;IoctObin375="11111101" ;IoctObin376="11111110" ;IoctObin377="11111111" ;

( while read line ;do

for octal in ${line} ;do
eval 'bin=${IoctObin'${octal}'}'

lineOut="${lineOut}${bin} "
binOutCount="${binOutCount}@"

if test "0${binOutCount}" = "0@@@@@@@@" ;then
echo "${lineOut}"
binOutCount="" ;lineOut=""
fi

done ; done ;

if test "${lineOut}" ;then
echo "${lineOut}"
fi
)
}

: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377 
111" |
#--------------------------------------------------------------test
octToBin_04
exit 0
試すのは大事
#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'
8進数を2進数に変換する。
入力は、0詰め3桁の8進数、000〜377まで、のみ。
▼処理
遅い要素を詰め込んだ版

$ time cat octalx064.txt | dash ./octToBin_05.sh 1>/dev/null
real	3m7.101s
user	2m30.626s
sys	0m36.898s
(187x64=11968[秒]) 772倍

$ time cat octalx064.txt | bash ./octToBin_05.sh 1>/dev/null
real	4m56.706s
user	3m50.208s
sys	1m2.387s

#--------------------------------------------------------------comment
octToBin_05(){

tr "\n" " " | tr -s " " | tr " " "\n" |
while read octal ;do

 oct76=`echo "${octal}" | cut -c 1 `
oct543=`echo "${octal}" | cut -c 2 `
oct210=`echo "${octal}" | cut -c 3 `

bin7=`expr ${oct76} / 2`
#eval 'bin7=`expr '`expr ${oct76} % 4 `' / 2 `'
bin6=`expr ${oct76} % 2`
bin5=`expr ${oct543} / 4`
eval 'bin4=`expr '`expr ${oct543} % 4 `' / 2 `'
bin3=`expr ${oct543} % 2`
bin2=`expr ${oct210} / 4`
eval 'bin1=`expr '`expr ${oct210} % 4`' / 2`'
bin0=`expr ${oct210}  % 2`

echo -n "${bin7}${bin6}${bin5}${bin4}${bin3}${bin2}${bin1}${bin0} "
binOutCount="`expr ${binOutCount} + 1`"

if test "${binOutCount}" -eq 8 ;then
echo ""
binOutCount="0" ;lineOut=""
fi

done

}

: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377
111" |
#--------------------------------------------------------------test

octToBin_05
exit 0
xargsすれば何でもいい、わけじゃないらしい

要するに、bcコマンドに8進数の数字を、一度にたくさん渡せばいいみたい。
一つずつ渡すと、期待するほど早くはなんない。

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'
■8進数を2進数に変換する -- bcコマンド版

出力はゼロ埋めや整形をしない。
fmtコマンドで簡単に折り返し表示するだけで済ませる。

▼高速なxargsと低速なxargs

・【A】セミコロン区切りで、まとめてechoする
echo obase=2;ibase=8;000;001;002;003;004;005;006;007;010;011;012;013;014;015;016;017; ?...

bcコマンドは、セミコロン区切りで数字を入力すると、まとめて処理してくれるようだ。
tr,sedコマンドで、1行の空白をセミコロンに入れ替えてから渡す。
結果、一つずつ渡すときと比較して、非常に高速になる。

foldで折り返すことで、一度に実行する数を制限した。
「-w 1000」の数を増やすと、さらに多少の高速化はできる。

$ time cat octalx4096.txt | ./octToBin_06.sh 1>/dev/null
real	0m12.071s
user	0m11.500s
sys	0m8.445s
(12[秒]) 0.8倍

・【B】ひとつずつechoする
echo obase=2;ibase=8;000 ?...
echo obase=2;ibase=8;001 ?...
echo obase=2;ibase=8;002 ?...

$ time cat octalx256.txt | dash ./octToBin_06.sh 1>/dev/null
real	0m56.445s
user	0m43.299s
sys	0m13.185s
(56x16=896[秒]) 57倍
#--------------------------------------------------------------comment
octToBin_06(){
# 【A】1行まとめて起動する、高速版
tr "\n" " " | tr -s " " | sed 's/ / ;/g' | fold -s -w 1000 | xargs -I @@ echo 'obase=2;ibase=8;@@' | bc | fmt

# 見た目だけなら10進数扱いで整形できるか?
#tr "\n" " " | tr -s " " | sed 's/ / ;/g' | fold -s -w 1000 | xargs -I @@ echo 'obase=2;ibase=8;@@' | bc |
#xargs printf "%08d " | fmt

# 【B】ひとつずつ起動する、低速版
#tr " " "\n" | xargs -I @@ echo 'obase=2;ibase=8;@@' | bc | fmt
}

: << '#--------------------------------------------------------------test'
echo "000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
120 121 122 123 124 125 126 127 130 131 132 133 134 135 136 137 
140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 
160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 
200 201 202 203 204 205 206 207 210 211 212 213 214 215 216 217 
220 221 222 223 224 225 226 227 230 231 232 233 234 235 236 237 
240 241 242 243 244 245 246 247 250 251 252 253 254 255 256 257 
260 261 262 263 264 265 266 267 270 271 272 273 274 275 276 277 
300 301 302 303 304 305 306 307 310 311 312 313 314 315 316 317 
320 321 322 323 324 325 326 327 330 331 332 333 334 335 336 337 
340 341 342 343 344 345 346 347 350 351 352 353 354 355 356 357 
360 361 362 363 364 365 366 367 370 371 372 373 374 375 376 377 
" |
#--------------------------------------------------------------test

octToBin_06
exit 0