シェルの「機能」の1つは、前にゼロの数字を8進数として解釈することです。
$ echo "$((00100))"
64
ただし、多くのシェルではこの「機能」を無効にする方法がないため、一連の数字を10進数(または他の基数)として解釈することは困難になります。
単一の数値のみを変換する必要がある場合は、トリミングを実行できるいくつかの外部プログラムがあります。
expr "00100" + 0
echo "00100" | sed 's/^0*//'
echo "00100" | grep -o '[^0].*$'
echo "00100" | awk '{print int($0)}'
echo "00100" | perl -pe '$_=int."\n";'
しかし、必要に応じて実行するには少し時間がかかります。複数の呼び出しでこれらの外部ツールを累積的に使用すると、待ち時間が大幅に長くなる可能性があります。発生した遅延を測定するために1000回以上の呼び出しを繰り返すと、次のような結果が得られます(秒単位)。
expr 1.934
sed 3.450
grep 3.775
awk 5.291
perl 5.064
もちろん(exprを除く)、ほとんどのツールは1000行のファイルを処理できます。
sed file 0.004
grep file 0.003
awk file 0.007
perl file 0.006
1000個の個別値がすべて同じ時点で使用できる場合です。
しかし、実際にはそうではありません。その場合、残りの答えは次のようになります。
ファイルのリストではなく、個々の整数ごとに外部ツールを呼び出すよりも高速な整数を抽出する基本的な(シェル用)方法はありますか?
各呼び出しが合計され、待ち時間がかなり長くなります。
数字に先行記号がある可能性があり、誤った数字を拒否しようとすると、処理がより複雑になります。
ベストアンサー1
POSIXでは8拡張が必要ですが、$((010))
一部のシェルは一貫性モードでない限り、デフォルトでは(または特定のコンテキストでのみ)これを行いません。特徴あなたは通常望んでいません。
使用すると、zsh
オプションによって制御されますoctalzeroes
(sh / kshエミュレーションを除いてデフォルトではオフ)。
$ zsh -c 'echo $((010))'
10
$ zsh -o octalzeroes -c 'echo $((010))'
8
$ (exec -a sh zsh -c 'echo "$((010))"')
8
では、mksh
このposix
オプションが制御されます(デフォルトではオフ)。
$ mksh -c 'echo "$((010))"'
10
$ mksh -o posix -c 'echo "$((010))"'
8
Bashにはこれをオフにするオプションはありませんが、ksh構文を使用して10進数として強制的に解釈できますが(kshとzshでも動作します)、(拡張で示すように)Yieldでは$((10#010))
動作しません。必要です(または根拠が間違った苦情との互換性のため)。bash
mksh -o posix
$((10#-010))
10#0 - 010
$((-10#-010))
-8
$((-10#010))
$((- 10#010))
zsh
-10
$ bash -c 'echo "$((10#010))"'
10
以下と比較してみてくださいksh93
。
$ ksh93 -c 'echo "$((010))"'
8
$ ksh93 -c '((a = 010)); echo "$a"'
8
そして:
$ ksh93 -c 'a=010; echo "$((a))"'
10
$ ksh93 -c 'printf "%d\n" 010'
10
$ ksh93 -c 'let a=010; echo "$a"'
10
$ ksh93 -c 'echo "$((010e0))"'
10
$ ksh93 -o letoctal -c 'let a=010; echo "$a"'
8
したがって、少なくともこれらのシェルに対して特別にコーディングする場合は、「バグのある機能」を解決する方法がいくつかあります。
ただし、POSIX移植可能なスクリプトを作成するときは、どちらも役に立ちません。この場合、示されているように先行ゼロを削除する必要があります。