GNU awk 구현 제한이 실제로 작동하지 않는 것처럼 보이는 이유는 무엇입니까?

GNU awk 구현 제한이 실제로 작동하지 않는 것처럼 보이는 이유는 무엇입니까?

이 페이지GNU awk 구현 제한에 관해서는 필드 크기 및 리터럴 문자열 크기에 대한 제한이 언급되어 있습니다 MAX_INT.

그러나 긴 문자열 리터럴을 변수로 선언하고 함수를 사용하여 길이를 찾으려고 하면 length문자열 길이가 308자를 초과하면 함수가 중단되는 것 같습니다. 아래 예:

BEGIN {
  avar=1234... #309 characters
  print length(avar) #prints 3 but prints right length when length < 309
} 

그러나 다음 명령줄은 1000자까지 작동합니다.

echo 1234... | awk '{print length($1)}' #tested and works for 1000 characters

CentOS 7 시스템을 사용하고 있으며 awk 버전은 4.0.2입니다.

이 차이가 발생하는 이유에 대한 제안 사항이 있습니까?

답변1

수행하려는 작업을 반복하기가 더 쉬울 수 있습니다.

awk 'BEGIN {
  avar='"$(printf '%0200d' 0)"' #309 characters
  print avar,length(avar) #prints 3 but prints right length when length < 309
} '

이는 0 1200개의 0으로 구성된 전체 목록이 awk에 의해 단일로 변환됨을 의미합니다 0. 이는 다음과 같은 의미인 것 같습니다.0이 200개 있는 정수를 쓰세요.

다른 값을 지정해 보겠습니다(8 뒤에 0이 200개 있음).

➤ awk 'BEGIN {
  avar='"$(printf '8%0200d' 0)"' #309 characters
  print avar,length(avar) #prints 3 but prints right length when length < 309
} '
799999999999999975786497770008289327579602620364018901185934007602774787484432604273570707237650014944220099327791059265457085874946227877115080328377919022968188728534319854489454506449337030839107584 201

이는 의 부동 소수점 근사치입니다 8e200. 이는 다음을 통해 쉽게 확인할 수 있습니다.

➤ awk 'BEGIN {
  avar='"$(printf '8%0200d' 0)"' #309 characters
  print avar,length(avar) #prints 3 but prints right length when length < 309
  printf "%15e\n",avar
} '
799999999999999975786497770008289327579602620364018901185934007602774787484432604273570707237650014944220099327791059265457085874946227877115080328377919022968188728534319854489454506449337030839107584 201
  8.000000e+200

따라서 코드 할당()에 지정된 숫자는 avar=숫자 값으로 (올바르게) 처리됩니다. 이중 부동 소수점 숫자는 최대 308까지의 지수만 저장할 수 있습니다(비정규 숫자 제외). 따라서 308비트를 초과하는 값은 부동소수점 숫자로 변환할 수 없습니다.

➤ ➤ awk 'BEGIN {
  avar='"$(printf '8%0308d' 0)"' #309 characters
  print avar,length(avar) #prints 3 but prints right length when length < 309
  printf "%15e\n",avar
} '
inf 3
            inf

단, 문자열이므로 avar="..."큰따옴표( )로 묶어도 문제가 없습니다.

➤ awk 'BEGIN {
  avar="'"$(printf '8%0600d' 0)"'" #309 characters
  print avar,length(avar) #prints 3 but prints right length when length < 309
} '
8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 601

데이터가 파이프(또는 파일)에서 오는 경우 데이터는 문자열로 간주되며( data + 0또는 이와 유사한 숫자로 변환되지 않는 한) 해당 길이는 문자 수입니다.

$ printf '8%02000d0\n' 0 | awk '{print length($1)}'
2002

관련 정보