Bash算術出力結果を10進数で表示

Bash算術出力結果を10進数で表示

Bashを使用して計算を実行し、16進入力を提供すると正しく計算されますが、結果は10進数として出力されます。これは普通ですか?明らかに結果を16進数で提供するので、結果を16進数で表示したいと思います。これを変える方法はありますか?

わかりましたprintf。しかし、printf増分などを使用して変数を少し更新するたびにそれを呼び出すのは奇妙です。

例えば

echo $((0xa+1))

結果は11私が予想した通りでしたb

答え1

$((0xa+1))算術式の評価を10進数表現に拡張する算術拡張です0xa+1

0xこの式の後には、16進整数定数、2進加算演算子、および10進整数定数はa+1続きません。0xa+1

私が知る限り、Bourneに似た唯一のシェルは、10以外の進数で整数算術拡張を実行でき、次の構文を使用して拡張するzsh進数を明示的に指定する必要があります。

$ echo $(( [#16] 0xa + 1 ))
16#B
$ echo $(( [##16] 0xa + 1 ))
B
$ set -o c_bases
$ echo $(( [#16] 0xa + 1 ))
0xB

同様に、以下をksh使用して整数変数に塩基を割り当てることができます。

$ typeset -i16 var
$ (( var = 0xa + 1 ))
$ echo "$var"
16#B
$ set -o c_bases
$ echo "$var"
0xB

(kshが16#bそこに提供され、c_basesオプション(オプションが設定されている場合ではなく16進数の0xBAD代わりに提供されます)が具体的です)。16#BAD0778#77octal_zeroeszsh

また、整数算術式( 、 、 、 などの算術演算子をzsh使用)内で変数を代入すると、整数型を取得し(真が割り当てられていない場合)、明示的な基数を持つ最も右の整数を継承します。定数の基本(たとえば、、、、)です。=--++*=-=+=10#120x120b11

たとえば。(( a = 0x10 + 0b1000 ))は24の整数変数としてtypeset -gi2 a=24定義され、2進数()に展開されます。a$a2#11000

info zsh 'Arithmetic Evaluation'詳細より。

bashkshではコピーしますtypeset -iが、コピーしませんtypeset -i<base>

bash数値を10以外の進数に変換するには、組み込みprintf関数を使用して他の人が示すように8と16を表すか、///を使用して異なる進数(サポートされる進数の範囲とその進数の範囲)を表すことができますdc。表現されているのは、これらの塩基の違いです))です。bckshzsh

たとえば、30進数に変換するには、次のようにします。

base30_dc() { echo "30o $1 p" | dc; }
base30_bc() { echo "obase=30; $1" | bc; }
base30_ksh93() { ksh93 -c 'printf "%..30d\n" "$@"' ksh "$@"; }
base30_zsh() { zsh -c 'echo $(([##30] $1))' zsh "$1"; }

以下を提供します。

$ base30_dc 1234
 01 11 04
$ base30_bc 1234
 01 11 04
$ base30_ksh93 1234
1b4
$ base30_zsh 1234
1B4

ただし、負の定数はdc符号で表されます。_whileは-バイナリ減算演算子ですdc逆ポーランド表記)。

$ base30_dc _1234
- 01 11 04
$ base30_dc '0 1234 -'
- 01 11 04

算術式内で認識される数値型もシェルによって異なります。

1230123POSIXでは、10進数、8進数、16進数の定数をそれぞれ認識するには、最小限と構文が必要です0x123。一部のシェルはデフォルトで8進数を優先またはmksh認識zshしません0123。これは、有用なものよりも頻繁に邪魔になります(たとえば、ゼロパディング番号を処理するとき)、特定のPOSIX互換モードが有効になっている場合(オプションまたはposix)のシミュレーション。mkshoctalzeroesshzsh

ksh、bash、およびzshは、12#123すべてのベースの入力数の表現をサポートします(やはり範囲は異なります)。

2#111zsh は 2 進数の置換で 0b111 をサポートします。_読みやすくするために内部番号を挿入します(たとえば、1_000_000または0xdead_beef)。

ksh93、zsh、yashは浮動小数点数(0.123または0,123ロケールに応じてksh93で)、、、1e20...をサポートします。 ksh93は、0xA.Bp-3(またはロケールに応じて0xA、Bp-3)などの16進浮動小数点表現もサポートしています。infnan

答え2

Bash(または実際には他のシェル)は、一般的なプログラミングに適したツールではありません。 Bashは、より複雑な演算はどこか浮動小数点演算も処理しません。殻はシェル、その中にシンプルで小さなスクリプトを書くことができますが、汎用プログラミング言語とは考えてはいけません。そうではありません。

このようなタスクを実行するためにbashを使用する必要があると主張する場合は、次に始まるより複雑な解決策を使用する必要がありますprintf

$ printf '%x\n' "$((0xa+1))"
b

良いニュースは、少なくとも次のことができることです。

$ printf '%x\n' 11
b

printfしたがって、1つから別のものに簡単に変換できます。つまり、毎回次を呼び出す必要はありません。

var=0xa

((var++))
echo "Var (decimal): $var"
printf 'Var (hex): %x\n' "$var"

上記のコマンドを実行すると、以下が印刷されます。

$ foo.sh
Var (decimal): 11
Var (hex): b

つまり、16進数で操作を実行でき、何かを印刷するまで表示方法を気にする必要はありません。

しかし、いいえ、シェルでこのようなことを行うための基本的な方法は見つかりません。なぜなら、シェルを設計された目的以外の目的で使用しようとしているからです。

関連情報