前に0がついた整数(移植可能)?

前に0がついた整数(移植可能)?

シェルの「機能」の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))動作しません。必要です(または根拠が間違った苦情との互換性のため)。bashmksh -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移植可能なスクリプトを作成するときは、どちらも役に立ちません。この場合、示されているように先行ゼロを削除する必要があります。

おすすめ記事