bashに組み込まれている関数のみを使用して、基本10から任意の基本変換

bashに組み込まれている関数のみを使用して、基本10から任意の基本変換

指定された文字セットを使用して、数値を基本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が好きではない人のために、他のシェルのいくつかの代替案を以下に見つけることができます。

関連情報