awk가 숫자가 아닌 경우 오류를 생성하도록 합니다.

awk가 숫자가 아닌 경우 오류를 생성하도록 합니다.

파일의 열을 합산하는 프로그램이 있습니다.

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

그러나 여기에는 문제가 있습니다. 숫자 데이터가 없거나 숫자가 누락된 파일을 제공하면 이를 0으로 해석합니다.

필드 중 하나를 숫자로 구문 분석할 수 없는 경우 오류가 발생하도록 하고 싶습니다.

입력 예는 다음과 같습니다.

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진수 숫자가 오고 선택적으로 "제곱"(지수)이 와야 합니다. 두 번째 필드 전체는 다음 형식 중 하나와 일치해야 합니다( ^및에 의해 고정됨 $). 이 질문의 목적을 위해 NAN 및 INFINITY 옵션은 여기서 생략되었습니다.

또 다른 옵션은 숫자 변환을 강제로 수행한 다음 이를 0과 비교한 다음, 선택적 + 또는 -로 시작하는 경우 원래 입력을 0으로 변환할 입력과 추가로 비교한 다음 0 또는 가 뒤따르는 것입니다. 마침표와 0:

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

답변2

나는 이것으로 끝났습니다 :

awk -v col=$col '
typeof($col) != "strnum" {
    print "Error on line " NR ": " $col " is not numeric"
    noprint=1
    exit 1
}
{
    sum+=$col
}
END {
    if(!noprint)
        print sum
}' $file

이는 GNU awk 확장인 typeof를 사용합니다. typeof($col)유효한 숫자이면 "strnum"을 반환하고 $col, 그렇지 않으면 "할당되지 않음"을 반환합니다.

바라보다 awk 변수의 유형을 확인할 수 있나요?

답변3

awk -v col=2 '
    $col+0==0 && $col!~/^[+-]?0/ { print "bad number " $col > "/dev/stderr" } 
    {sum+=$col}
    END{print sum}' input-file

.0를 처리하거나 유효한 표현으로 사용하려는 경우 .0e+33이를 복잡하게 만들 수 있습니다 . 문자열을 숫자로 변환할 때 후행 쓰레기( 또는 모두 14 와 같음) 0는 무시됩니다.awk"1.4e1e3"+0"1.4e1.e7"+0"14+13"+0

답변4

제가 사용하는 작은 비결은 문자열에서 제곱근을 구하는 것입니다. awk올바른 결과를 얻기 위해 최선의 노력을 다할 것이므로 후행 0이 숫자가 아닌 경우 이 방법은 적합하지 않습니다.

if ( sqrt(_varname) ) {
 print "this " _varname " is a (positive) number"
} else {
 print "this " _varname " is not a number..."
}

관련 정보