awk의 printf가 127보다 큰 문자 값을 멀티바이트 문자로 해석하는 이유는 무엇입니까?

awk의 printf가 127보다 큰 문자 값을 멀티바이트 문자로 해석하는 이유는 무엇입니까?

ASCII 문자 범위는 0부터 127까지입니다. 이 범위 내에서 %c 형식 지정자를 사용하는 awk의 printf는 1바이트의 데이터를 출력합니다.

$ awk 'BEGIN{printf "%c", 97}'
a

$ awk 'BEGIN{printf "%c", 127}' | xxd
00000000: 7f

$ awk 'BEGIN{printf "%c", 127}' | xxd -b
00000000: 01111111

그러나 127보다 큰 값의 경우 여러 바이트를 인쇄합니다.

$ awk 'BEGIN{printf "%c", 128}' | xxd
00000000: c280

$ awk 'BEGIN{printf "%c", 128}' | xxd -b
00000000: 11000010 10000000

0xc280의 의미는 무엇입니까? awk가 0x80 대신 이 문자를 출력하는 이유는 무엇입니까?

답변1

이것은UTF-8코딩. 11000010은 2바이트 시퀀스를 시작하고(처음 2비트는 클리어 비트로 설정됨) 유효한 비트는 00010000000(첫 번째 바이트의 마지막 5비트, 두 번째 바이트의 마지막 6비트)이며 이는 128입니다. .

AWK는 로케일이 UTF-8을 사용하도록 설정되어 있으므로 이를 출력합니다. UTF-8이 아닌 로케일로 전환하여 차이점을 확인할 수 있습니다.

$ LC_ALL=C awk 'BEGIN{printf "%c", 128}' | xxd -b
00000000: 10000000

답변2

로케일이 UTF8, POSIX 또는 C인지 여부에 관계없이 임의의 바이트를 인쇄하도록 awk를 얻는 한 가지 트릭은 부호 없는 바이트 조례 값에 256의 큰 배수를 추가하여 새 숫자가 유니 0x10FFFF코드 14 제한 사양을 초과하도록 하는 것입니다.

다음은 UTF8로 인코딩된 문자를 인쇄하기 위해 gawk 바이트 모드에서 임의의 바이트에 액세스하는 방법에 대한 데모입니다. gawk 유니코드 모드에서도 동일한 방법을 사용하여 임의의 바이트에 액세스할 수 있습니다.

 gawk -e 'BEGIN { printf("%c",50000) }' | od -baxco -t dC

0000000   354 215 220                                                    
           ?  8d  90                                                    
             8dec    0090                                                
          썐  **  **                                                    
           106754  000220                                                
          -20-115-112                                                    
0000003

% gawk -b -e 'BEGIN { printf("%c%c%c",
                             (-20)+8^8,
                            (-115)+8^8,
                            (-112)+8^8) }' | od -baxco -t dC
0000000   354 215 220                                                    
           ?  8d  90                                                    
             8dec    0090                                                
          썐  **  **                                                    
           106754  000220                                                
          -20-115-112                                                    
0000003

% gawk -e 'BEGIN { printf("%c%c%c%c",\
                                      \
                   0xAB+8^8, 0xBA+8^8, \
                   0xCA+8^8, 0xFE+8^8) }' \
 | god --endian=big -baxco -t dCxI

0000000  253  272  312  376
           +    :    J    ~
             abba      cafe
           ?    ?    ?    ?
           125672    145376
         -85  -70  -54   -2
                   abbacafe
0000004

이 방법은 로케일에 관계없이 작동합니다.

mawk-1, mawk2-beta 및 nawk의 경우 부호 없는 바이트 값에서 256을 빼고 printf("%c")음수를 사용할 수도 있습니다. gawk는 이를 허용했지만 최신 버전에서는 이를 비활성화했을 수 있습니다.

관련 정보