Bashの異なるコードポイントでASCII文字を印刷するにはどうすればよいですか?


12

ASCIIテーブルには、さまざまな数値システムのコードポイントを持つ「J」文字が存在します。

Oct   Dec   Hex   Char
112   74    4A    J

printf '\112'またはを印刷することにより、この文字を8進コードポイントで印刷 できecho $'\112'ます。10進数と16進数のコードポイントプレゼンテーションで同じ文字を印刷するにはどうすればよいですか?


回答:


12

16進数:

printf '\x4a'

12月:

printf "\\$(printf %o 74)"

16進数の代替:-)

xxd -r <<<'0 4a'

ありがたいことに、これはでも機能しawkます。
Sridhar Sarnobat

6

zsh

$ printf '\x4a\n' # Hex
J
$ printf "\\$(([##8]74))\n" # Dec
J

Unicodeコードポイントから(現在の文字セットの)文字を取得するには:

$ printf '\U1F42E\n' # Hex
🐮
$ printf "\\U$(([##16]128046))\n" # Dec
🐮

答えはまた、「F0 9F 90 AE」進コードでこの顔を印刷する方法を喜ば
viavad


6

一般に、シェルは、変数として16進数、10進数、10進数を理解できますintegers

$ declare -i v1 v2 v3 v4 v5 v6 v7
$ v1=0112
$ v2=74
$ v3=0x4a
$ v4=8#112
$ v5=10#74
$ v6=16#4a
$ v7=18#gg
echo "$v1 $v2 $v3 $v4 $v5 $v6 $v7"
74 74 74 74 74 74 304

または、それらは「算術拡張」の結果です。

$ : $(( v1=0112, v2=74, v3=0x4a, v4=8#112, v5=10#74, v6=16#4a, v7=18#gg ))
$ echo "$v1 $v2 $v3 $v4 $v5 $v6 $v7"
74 74 74 74 74 74 304

したがって、変数値に属する文字を出力する1つの方法が必要です。
ただし、次の2つの方法があります。

$ var=$((0x65))
$ printf '%b\n' "\\$(printf '0%o' "$var")"
e

$ declare -i var
$ var=0x65; printf '%b\n' "\U$(printf '%08x' "$var")"
e

2つのprintfが必要です。1つは値を16進数の文字列に変換するためのもので、もう1つは実際に文字を出力するためのものです。

2番目は、任意のUNICODEポイントを出力します(コンソールが正しく設定されている場合)。
例えば:

$ var=0x2603; printf '%b\n' "\U$(printf '%08x' "$var")"

雪だるま。

UTF-8表現を持つ文字がようf0 9f 90 aeです0x1F42Eそれcow face site:fileformat.info取得するために検索してください

$ var=0x1F42F; printf '%b\n' "\U$(printf '%08x' "$var")"
🐮

:UNICODEの方法に問題があり、4.3より前のbash(そのバージョン以降で修正)では、UNICODEポイント128と255(10進数)の間の文字が正しく印刷されない場合があります。


参考文献

内側の第四段落PARAMETERSman bash

変数に整数属性が設定されている場合、$((...))展開が使用されていなくても、値は算術式として評価されます(下記の算術展開を参照)。

の「算術評価」の内部man bash

先頭が0の定数は、8進数として解釈されます。先頭の0xまたは0Xは16進数を示します。それ以外の場合、数値は[base#] nという形式になります。オプションの基数は、算術基数を表す2から64までの10進数で、nはその基数の数値です。base#を省略すると、base 10が使用されます。9より大きい数字は、小文字、大文字の@、_の順に表示されます。baseが36以下の場合、小文字と大文字を同じ意味で使用して、10〜35の数値を表すことができます。


@StéphaneChazelasさて、コードポイントは(常に)バイト値ではありません。Bash(4.3より前のバージョン)は、コードポイントのバイト値を提供します。つまり、文字é(10進数:351、12進数:233、16進数:0xE9)はprintf '\351'0xE9常にバイト値を印刷するため、誤って印刷されます。機能する可能性のあるエンコーディングISO-8859-1(およびいとこ)を備えた端末の場合、utf-8でエンコードされた端末では、バイト値は0xE9 として表示されます。cont ....
アイザック

@StéphaneChazelas 一例として、「bash 4.2が正しくエンコードされない」に気づいて検索するのは私が最初ではありません。bash 4.3以降では修正されています。
Isaac

OK。私はあなたが今何を意味するかを理解しています(私はあなたの答えの以前のバージョンに従って4.3でテストしていました)。bash-4.2のみであることに注意してください。bash-4.1はサポートしていません\u(zshによる)。
ステファンChazelas


0

POSIX Awk stdlibライブラリを使用できます。

$ awklib 'BEGIN {print str_chr(74)}'
J

$ awklib 'BEGIN {print str_chr(+base_conv("4A", 16, 10))}'
J

$ awklib 'BEGIN {print str_chr(+base_conv(112, 8, 10))}'
J

$ awklib 'BEGIN {print str_chr(+base_conv(1001010, 2, 10))}'
J

0

変換する数値のリストがあり、関数呼び出しを避けて各文字のサブシェルを作成したい場合は、事前にASCIIセットを定義できます。

ascii=$(for x in {0..9} {A..F}; do for y in {0..9} {A..F}; do echo -ne "\x$x$y"; done; done)

null文字は除外されるため、すべての文字は1だけオフセットされることに注意してください。

次に、次のようなものを使用します(1行に1つの数値を想定しています):

while read c; do out+="${ascii:$c-1:1}"; done <<< "$in"
echo "$out"

0

使用するすべての変換はprintf次のとおりです。

printf "%o" "'J" # 112 (oct)
printf "%d" "'J" # 74 (dec)
printf "%x" "'J" # 4a (hex)

printf '\112' # J (oct)
printf "\x$(printf %x 74)" # J (dec, requires double conversion)
printf '\x4a' # J (hex)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.