指定された文字セットを使用して、数値を基本10から任意の基本に変換するbashコマンドを作成しようとしています(たとえば、文字azを使用して基本26に変換しますが、実際にはユースケースではありません)。
私持つこの問題は以前は解決されましたが、bashでは解決されておらず(私の経験は限られています)、かなり長い時間が経っても解決されませんでした。
どんなアイデアがありますか?
答え1
似たようなものがありました。
#!/bin/bash
#
# usage: convert_base <number-to-convert> <output-base> <output-digit-string>
#
# example:
# $ convert_base 3735928559 16 "0 1 2 3 4 5 6 7 8 9 A B C D E F"
# DEADBEEF
decimal_number=$1
output_base=$2
read -ra output_digits <<< "$3"
# TODO various assertions
if ((decimal_number == 0)); then
output=${output_digits[0]}
else
while ((decimal_number > 0)); do
digit=$(( decimal_number % output_base ))
output="${output_digits[digit]}$output"
decimal_number=$(( decimal_number / output_base ))
done
fi
printf '%s\n' "$output"
答え2
2-64を10進数で使用する内蔵BASH$((デフォルト#番号))
> echo $(( 36#B002RD3KCS ))
1117165531505356
> echo $(( 16#FF ))
255
復元変換は、標準のbc +ヘルパー機能を使用して実行できます。
# base10 to base2..base52
# Usage: decimal_to_anybase <OtputBase> <DecimalNum>
function decimal_to_anybase()
{
BASE52=($(echo {0..9} {A..Z} {a..z})); # array of 'base_digits'
base="$1"; # output base 2..52
arg="$2"; # source decimal
res=$(bc <<< "obase=$base; $arg")
if [ "$base" -le 16 ]; then # bases 2..16 returned as is
echo "$res"
else # bases 17..52 returned as array indexes
for i in $res; do
echo -n ${BASE52[$(( 10#$i ))]} # output BASE52[base_digit]
done && echo
fi
}
> decimal_to_anybase 36 1117165531505356
B002RD3KCS
答え3
おそらく当然のことかもしれませんが、bashにはprintf
基本8と16を実行できる組み込み関数があります。
$ printf '%o\n' 1234
2322
$ printf '%#o\n' 1234
02322
$ printf '%x\n' 1234
4d2
$ printf '%#x\n' 1234
0x4d2
$ printf '%X\n' 1234
4D2
$ printf '%#X\n' 1234
0X4D2
16進浮動小数点数:
$ LC_ALL=C printf '%a\n' 1234.56
0x9.a51eb851eb851ecp+7
$ LC_ALL=C printf '%A\n' 1234.56
0X9.A51EB851EB851ECP+7
LC_ALL=C
(10進数の基数文字があることを確認するためにここで使用されます.
)
ただし、より高度なシェル(zshやksh93など)を必要とする他の基盤はサポートされておらず、手動で実行することはできません。
結果を変数に保存するには:
printf -v oct %o 1234
以下より効率的です。
oct=$(printf %o 1234)
bashから(ksh93または一部のBSDのshとは反対)プロセスを分岐し、結果をパイプを介して送信することを意味します。
Bashが好きではない人のために、他のシェルのいくつかの代替案を以下に見つけることができます。