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ビット、2番目のバイトの最後の6ビット)です。これは128です。 。

AWKはロケールがUTF-8を使用するように設定されているため、それを出力します。 UTF-8以外のロケールに切り替えることで、違いを確認できます。

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

答え2

ロケールがUTF8、POSIX、またはCであるかどうかにかかわらず、任意のバイトを印刷するようにawkを取得する1つのトリックは、符号なしバイト条例値に256の大きな倍数を追加し、新しい数値がUnicode 0x10FFFF14制限仕様を超えるようにするです。

以下は、UTF8でエンコードされた文字を印刷するためにgawkバイトモードでランダムバイトにアクセスする方法のデモです。 gawk Unicodeモードでも、同じ方法で任意のバイトにアクセスできます。

 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はこれを許可しましたが、最新バージョンではこれを無効にした可能性があります。

関連情報