awk変数の型を確認できますか?

awk変数の型を確認できますか?

私はawkのgawkバージョンを持っています。存在するこれgawk マニュアルの一部には、awk 変数がさまざまなタスクでどのように処理されるかを決定する「プロパティ」があることが示されています。

たとえば、" +3.14"入力を解析して取得した形式の文字列にはこのSTRNUM属性があるため、数値と比較すると数値として機能しますが、awkプログラムで定義されているのと同じ文字列にはこの属性はありません。

OTOH、このような文字列は、プログラムで定義されていてもコードが1を印刷するため、"3.14"明らかに属性を持ちます。そしてorと定義すると、orは0を印刷するので属性はありません。STRNUMx = "3.14" { print x == 3.14 }"+3.13"" 3.14"STRNUMx = "+3.14" { print x == 3.14 }x = " 3.14" { print x == 3.14 }

変数型のこの単純さは微妙なバグにつながる可能性があると思います。それでは、この状況をデバッグするのに役立つように、変数にどのような「属性」があるかを知る方法はありますか?つまり、変数の型が何であるかを知ることができますか?

答え1

awkは4種:「数字」、「文字列」、「数字 - 文字列」、および「未定義」。これは機能検出済み:

function o_class(obj,   q, x, z) {
  q = CONVFMT
  CONVFMT = "% g"
    split(" " obj "\1" obj, x, "\1")
    x[1] = obj == x[1]
    x[2] = obj == x[2]
    x[3] = obj == 0
    x[4] = obj "" == +obj
  CONVFMT = q
  z["0001"] = z["1101"] = z["1111"] = "number"
  z["0100"] = z["0101"] = z["0111"] = "string"
  z["1100"] = z["1110"] = "strnum"
  z["0110"] = "undefined"
  return z[x[1] x[2] x[3] x[4]]
}

3番目のパラメータの場合、splitスペースや部分は必要ありません。objそれ以外の場合は区切り文字として扱われます。私は\1 基準として選ぶスティーブンのアドバイス。この関数は内部CONVFMT 切り替えを実行するため、CONVFMT関数呼び出し時に値に関係なく正しい結果を返す必要があります。

split("12345.6", q); print 1, o_class(q[1])
CONVFMT = "%.5g"; split("12345.6", q); print 2, o_class(q[1])
split("nan", q); print 3, o_class(q[1])
CONVFMT = "%.6G"; split("nan", q); print 4, o_class(q[1])

結果:

1 strnum
2 strnum
3 strnum
4 strnum

フルテストコレクション:

print 1, o_class(0)
print 2, o_class(1)
print 3, o_class(123456.7)
print 4, o_class(1234567.8)
print 5, o_class(+"inf")
print 6, o_class(+"nan")
print 7, o_class("")
print 8, o_class("0")
print 9, o_class("1")
print 10, o_class("inf")
print 11, o_class("nan")
split("00", q); print 12, o_class(q[1])
split("01", q); print 13, o_class(q[1])
split("nan", q); print 14, o_class(q[1])
split("12345.6", q); print 15, o_class(q[1])
print 16, o_class()

結果:

1 number
2 number
3 number
4 number
5 number
6 number
7 string
8 string
9 string
10 string
11 string
12 strnum
13 strnum
14 strnum
15 strnum
16 undefined

注目すべき弱点:次の「数値文字列」のいずれかを指定すると、関数は「数値」を誤って返します。

  • 整数
  • inf
  • -inf

整数の場合、説明は次のとおりです。

整数値とまったく同じ数値は、文字列を引数として関数を呼び出すのと同等の方法で文字列に変換する必要がありsprintfます。%dfmt

ただし、この作業infも実行する必要があります。つまり、上記のいずれもこの変数-infの影響を受けません。CONVFMT

CONVFMT = "% g"
print "" .1
print "" (+"nan")
print "" 1
print "" (+"inf")
print "" (+"-inf")

結果:

 0.1
 nan
1
inf
-inf

実際には関係ありません。アヒルテスト

答え2

typeof()GNU Awk 4.2以降、テストバージョンのリリースノートに示すようにこれを確認する新機能があります。

  1. 新しいtypeof()関数を使用して、変数または配列要素が配列、正規表現、文字列、または数値であるかどうかを示します。 isarray() 関数は廃止され、typeof() に置き換えられました。

これで、次のように話すことができます。

$ awk 'BEGIN {print typeof("a")}'
string
$ awk 'BEGIN {print typeof(1)}'
number
$ awk 'BEGIN {print typeof(a[1])}'
unassigned
$ awk 'BEGIN {a[1]=1; print typeof(a)}'
array
$ echo ' 1 ' | awk '{print typeof($0)}'
strnum

答え3

ぼんやりと同じですPROCINFO["identifiers"]変数情報を含む配列。次のように使用してください。PROCINFO["identifiers"]["your_variable_name"]返される可能な値は、「array」、「built-in」、「extended」、「scalar」、「untyped」、「user」のいずれかです。

scalar文字列と数字を含む一般的なものは1つだけです。通訳者はgawk最善を尽くすだけです。

variable + 0変数が数値変数として扱われていることを確認するために、どこかで重複しているように見える変数が表示されるのawkには理由があります。

一部はこの段落を参照してください。暗黙の変換トリック

答え4

gawk < 4.2 (RHEL7 基本バージョン: gawk 4.0.2)
の場合、fedorqui 応答と gawk 4.2リリース発表

14.新しいtypeof()関数を使用して、変数または配列要素が配列、正規表現、文字列、または数値であるかどうかを示します。

$ cat test.txt 
11.11
-0
ext4
0
xfs
0.123
11111.111111
-3333.3333333

$ cat test.txt | awk '{if($1!=0 && $1+0==0) {print $1" non-numeric"} else {print $1" numeric"} }'
11.11 numeric
-0 numeric
ext4 non-numeric
0 numeric
xfs non-numeric
0.123 numeric
11111.111111 numeric
-3333.3333333 numeric

鈍い場合>= 4.2

$ cat test.txt | awk '{{print $1" ,"typeof($1)}}'
11.11 ,strnum
-0 ,strnum
ext4 ,string
0 ,strnum
xfs ,string
0.123 ,strnum
11111.111111 ,strnum
-3333.3333333 ,strnum

関連情報