gawkがデータを入力するときに「0123」を10進数として扱うのはなぜですか?

gawkがデータを入力するときに「0123」を10進数として扱うのはなぜですか?

によると、$ man gawkこのstrtonum()関数は文字列を数値に変換できます。

strtonum(str) strをチェックし、その値を返します。 strが前に0で始まる場合、8進数として扱われます。 strが先行0xまたは0Xで始まる場合、16進数として扱われます。それ以外の場合は10進数と見なされます。

文字列がで始まる場合、0数字は8進数と見なされ、で始まると0x16進数と見なされます。

関数の理解を確認するために、次のコマンドを実行しました。

$ awk 'END { print strtonum("0123") }' <<<''
83

$ awk 'END { print strtonum("0x123") }' <<<''
291

文字列は"0123"8進数を含むものとして正しく処理され、10進数に変換されます83。同様に、文字列は"0x123"16進数を含むものとして正しく処理され、10進数に変換されます291

これで同じコマンドを実行しますが、数値文字列をプログラムテキストから入力データに移動すると、次のことが起こります。

$ awk 'END { print strtonum($1) }' <<<'0123'
123

$ awk 'END { print strtonum($1) }' <<<'0x123'
291

2番目の結果が前のコマンドと同じであることは理解されますが、最初の結果は理解されません。 gawkが8進数を特徴とする先行文字で始まって0123も、これを10進数として扱うのはなぜですか?0

私はこれが何か関連していると思う。文字列属性何らかの理由で、1 gawkはこのプロパティを提供します0123が、次のものを提供しないからです0x123

$ awk 'END { print typeof($1) }' <<<'0123'
strnum

$ awk 'END { print typeof($1) }' <<<'0x123'
string

1は次のように発生する可能性があります。多様性awk実装間:

明確にするために、いくつかのソースの文字列しかありません(ここではPOSIX仕様の引用):[...]その値が数値の場合(先行および末尾のスペースが許可されている場合、 16進数と8進数をサポートする実装には違いがあります。、inf、南...)。


私はgawkバージョンを使用しており4.2.62、その出力は$ awk -V次のようになります。

GNU Awk 4.2.62, API: 2.0 (GNU MPFR 3.1.4, GNU MP 6.1.0)

答え1

strnumこれは、GAWK バージョン 4.2 の一般的な処理に関連しています。

入力値数字のように見えたstrnum値として扱われ、内部的に文字列と数値型の両方を持つようにマークされます。 「0123」は数字のように見えるので、使用されますstrnumstrtonum文字列と数値入力を処理するように設計されています。まず数字を探します。、入力番号が見つかると、変換なしでその数値を返します。

NODE *
do_strtonum(int nargs)
{
        NODE *tmp;
        AWKNUM d;

        tmp = fixtype(POP_SCALAR());
        if ((tmp->flags & NUMBER) != 0)
                d = (AWKNUM) tmp->numbr;
        else if (get_numbase(tmp->stptr, tmp->stlen, use_lc_numeric) != 10)
                d = nondec2awknum(tmp->stptr, tmp->stlen, NULL);
        else
                d = (AWKNUM) force_number(tmp)->numbr;

        DEREF(tmp);
        return make_number((AWKNUM) d);
}

これにより、「0123」は数字123になり、strtonumすぐに返されます。

「0x123」は(上記のリンクで定義されている規則に従って)数字のように見えないため、文字列として扱われ、期待どおりに処理されますstrtonum

数値は次のように定義されます。AWKから:

入力文字列は、2つの部分、つまり空にすることができる最初の空白文字シーケンス(以下で定義)に分割されます。スペース()) と浮動小数点定数として解釈されるターゲットシーケンスです。

トピックシーケンスの予想される形式は、オプションまたは'+'シンボル'-'、オプションで<ピリオド>を含む空でない数値シーケンス、オプションのインデックス部分が続きます。指数部分は、'e'または'E'、オプションの記号、最後に1つ以上の小数点以下の桁数で構成されます。

最初の数字または<ピリオド>で始まるシーケンス(2つの最初のもの)は、C言語で浮動定数として解釈されます。指数部または<ピリオド>がすべて表示されない場合、最後の数字の後の文字は文字列と見なされます。ターゲットシーケンスが<ハイフン - 減算>で始まる場合、変換によって生成された値は無効になります。

関連情報