awkが数値でない場合はエラーを生成します。

awkが数値でない場合はエラーを生成します。

ファイルの列を合計するプログラムがあります。

awk -v col=2 '{sum+=$col}END{print sum}' input-file

しかし、ここに問題があります。数値データがない場合、または数値が欠落しているファイルを指定した場合は、それをゼロと解釈します。

フィールドの1つを数値に解析できない場合は、エラーが発生したいと思います。

入力例は次のとおりです。

bob 1
dave 2
alice 3.5
foo bar

「bar」は数字ではないので、エラーを無視するのではなく、エラーが発生したいと思います。

ベストアンサー1

これをテストする合理的な方法は、次のようなテストを使用してフィールドを比較することです。strtod、どちらがawkの使い方文字列を数値に変換:

$2 !~ / *[+-]?[[:digit:]]/ { print "NAN: " $2; exit 1; }

上記とstrtodの違いは、INFINITYまたはNANを「数値」と見なさないことです。 awkのデフォルトのフィールド分割動作によっては、前の空白の要件が軽減されることがあります。つまり、フィールドには先行スペースは含まれません。

$2 !~ /[+-]?[[:digit:]]/ { print "NAN: " $2; exit 1; }

Stéphaneのコメントここに答えてください:

$2 !~ /^[+-]?([[:digit:]]*\.?[[:digit:]]*([eE][-+]?[[:digit:]]+)?|0[xX][[:xdigit:]]*\.?[[:xdigit:]]*([pP][-+]?[[:digit:]]+)?)$/ { print "NAN: " $2; exit 1; }

やや良い読みやすさのために、正規表現は次のようになります。

/^[+-]?([[:digit:]]*\.?[[:digit:]]*([eE][-+]?[[:digit:]]+)?|\
        0[xX][[:xdigit:]]*\.?[[:xdigit:]]*([pP][-+]?[[:digit:]]+)?)$/

...目的は、可能な前に+または-を許可し、その後に浮動小数点または16進数が続くことを許可することです。浮動小数点数には、オプションの先行数字、オプションの区切り記号(ここではピリオドで固定.)、その後に数字、オプションで指数が続きます。 16進数は0xまたはで始まり、0Xその後に16進数、区切り記号、追加の16進数字が続き、オプションで「2乗」(指数)が続く必要があります。 2番目のフィールド全体は、次のいずれかの形式と一致する必要があります(^およびによって固定されています$)。この質問の目的のために、NANおよびINFINITYオプションはここで省略されています。

もう1つのオプションは、数値変換を強制し、それを0と比較し、オプションの+または-で始まる場合、元の入力を0に変換する入力とさらに比較してから0または次に続くことです。ピリオドと0:

{ number=0 + $2;
  if (!number && $2 !~ /^[+-]?(0+)|\.0+/)
    print "NAN: "$2;
}

おすすめ記事