나는 awk의 gawk 버전을 가지고 있습니다. 존재하다이것gawk 매뉴얼의 일부에는 awk 변수가 다양한 작업에서 처리되는 방법을 결정하는 "속성"이 있다고 명시되어 있습니다.
예를 들어, " +3.14"
입력을 구문 분석하여 얻은 형식의 문자열에는 이 STRNUM
속성이 있으므로 숫자와 비교할 때 숫자로 동작하지만 awk 프로그램에 정의된 동일한 문자열에는 이 속성이 없습니다.
OTOH, 이와 같은 문자열은 프로그램에 정의되어 있더라도 코드가 1을 인쇄하기 때문에 "3.14"
분명히 속성을 갖습니다 . 그리고 or 로 정의하면 or는 0을 인쇄하기 때문에 속성이 없습니다 .STRNUM
x = "3.14" { print x == 3.14 }
"+3.13"
" 3.14"
STRNUM
x = "+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]]
}
세 번째 매개변수인 경우 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
해야 합니다.%d
fmt
그러나 이 작업 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부터 테스트 버전의 릴리스 노트에 표시된 대로 이를 확인하는 새로운 기능이 있습니다 .
- 새로운 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
문자열과 숫자를 포함하는 General 은 하나만 있습니다 . 통역사는 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