以下を使用して、bashでintからcharおよびcharからintに変換しました。しかし、私はprintf \\$(printf '%03o' $1)
または_printf '%d' "'$1"
_の仕組みを理解していません。 printf \\$(printf '%03o' $1)
と_printf '%d'
_の仕組みを説明してください。
_#!/bin/bash
# chr() - converts decimal value to its ASCII character representation
# ord() - converts ASCII character to its decimal value
chr() {
printf \\$(printf '%03o' $1)
}
ord() {
printf '%d' "'$1"
}
ord A
echo
chr 65
echo
_
_printf '\101'
_ここで_101
_は8進数で、その値のバイトを出力します。
ASCII端末に送信されると、A
はASCIIの文字65(8進数101)であり、すべてのASCII互換文字セット(最新の文字セットを含む)であるため、A
としてレンダリングされます。一部のIBMシステムでまだ使用されているEBCDICのもの)。
に
_printf \\$(printf '%03o' $1)
_
どちらを書いておくべきか:
_printf "\\$(printf '%03o' "$1")"
_
パラメータ展開(_$1
_など)、またはコマンド置換($(...)
)を引用符で囲まないままにすることは、Bourneのようなシェルではsplit + glob演算子であり、ここでは不要です。
printf '%03o' "$1"
_は、_$1
_の数値を3桁の8進数に変換しますprintf "\\$(...)"
は、その8進数を_\
_に追加し(二重引用符内の_\\
_は_\
_になります)、対応するバイト値を出力するようにprintf
に渡します。これは、文字セットが文字ごとに1バイトのロケール(_iso8859-1
_など)でのみ機能するか、マルチバイト文字セットのロケールでは、0〜127の値でのみ機能することに注意してください。
bash
では、
_printf '%d\n' "'A"
_
文字A
(または、少なくともmbtowc()
から返される値で、GNUシステムでは少なくともUnicodeコードポイント)のUnicodeコードポイントを出力します。
他のいくつかの実装(スタンドアロンGNU printf
ユーティリティを含む)は、代わりに文字の最初のバイトの値を返します。
A
のようなASCII文字やASCIIベースのシステムでは、違いはありませんが、その他の場合は重要です。たとえば、ギリシャ語の_α
_文字(U + 03B1)は次のようにエンコードされます。
Bashの_printf '%d\n' "'α"
_は、常に_945
_(16進数で0x03b1)を出力します。これは、ロケール(少なくともGNUシステムでは)に関係なく、_α
_のUnicodeコードポイントですが、その他ロケールに応じて、225、206、または166を返す場合があります。
これらのchr
とord
は、ASCII文字(または値0〜127)の場合、またはすべての文字(値0〜0)の_iso8859-1
_文字セットを使用するロケールでは互いに逆になっていることがわかります。 255)。
ord()
がUnicodeコードポイントを返すことを意図している場合、逆(Unicodeコードポイントに対応する文字を出力する)は次のようになります。
_chr() {
printf "\U$(printf %08X "$1")"
}
_
(bash
4.3以上を想定(_\UXXXXXXXX
_は4.2で追加されましたが、4.3までの文字U + 0080からU + 00FFまでは正しく機能しませんでした))。
次に、任意のロケールで:
_$ ord α
945
$ chr 945
α
_
または、ord()
が(現在のロケールで)指定された文字のエンコーディングのバイトの値を返す場合:
_ord() {
printf %s "$1" | od -An -vtu1
}
_
そして、chr()
がそれらのバイトを出力するために:
_chr() {
printf "$(printf '\\%o' "$@")"
}
_
次に、たとえばUTF-8ロケールで:
_$ ord α
206 177
$ chr 206 177
α
_
(あなたの_ord α
_は945を与え、あなたのchr
は_chr 945
_と_chr 206 177
_の両方にゴミを与えるでしょう)。
または、_iso8859-7
_を使用するロケールで:
_$ ord α
225
$ chr 225
α
_
(あなたの_ord α
_は945を与えますが、GNUシステム上でprintf
が_/usr/bin/printf
_に置き換えられた場合は225を与える可能性があります)。
内側の_printf '%03o' $1
_は、_$1
_(つまり65)の値を8進値(65-> 101)として返します。
外側のprintf \\$(..)
は、8進値で表される文字を出力します。
_man printf
_行を参照してください:
8進数NNN(1から3桁)の\ NNNバイト
_printf '%d' "'$1"
_の場合、_'
_を指定して_$1
_を単一の文字定数として扱う必要があることを示します。そうでない場合、printfは値が無効な数値であることを示すエラーをスローします。文字定数の値はprintf
によって使用され、10進形式で印刷されます_"%d"
_
printf \\ $(printf '%03o' $ 1) #する必要があります... printf "$(printf '\\%03o' "$1")"
最初のprintf
は、2番目の出力を使用して文字を生成します。それを復号化するには、逆方向に作業する必要があります。
2番目のprintf
は、整数値($1
から)を8進整数('%03o'
形式)に変換するために使用されます。
$ printf '%03o' 12
014
$ printf '%03o' 65
101
$ printf '%03o' 255
377
次に、その結果は\
に相当するものと連結されます(シェルに対するその特別な意味を回避するために、二重にする(または引用する)必要があります)。結果の文字列\101
は、printfによってバイトの8進値として解釈されます。ただし、最大3桁(printfのほとんどのシェル実装では)のみです。 3桁の8進数字のみの解釈は、そのタイプのフォーマットが1バイト0-255(または8進数では0-377)で使用されることを意図しているためです。そのため、ほとんどのprintf実装は、8進数を1つだけに変換しますbyte。そのバイトがコンソールで使用されているロケールのASCII文字を表す場合、その文字が出力されます。
$ printf \\101\\n
A
$ printf \\377\\n
�
必要なロケールの影響を受ける文字(バイトではない)を出力するには:
たとえば、bash(4.3+)では:
$ printf \\U263A\\n
☺
printf
は多くの桁を印刷できることに注意してください。
$ printf '%03o\n' 1495195076287004671
122777777777777777777
ただし、最初の3つだけが8進数として受け入れられます。
$ printf '\122777777777777777777'
R777777777777777777 # Note the R in the front.
printf '%d' "'$1"
データ(形式ではない)文字列は、外側の引用符が削除され、結果の文字列は'
で始まります。 '
または"
で始まる文字列は、printfにとって特別です。それらの文字列について、形式が数値の場合、最初の文字の値が(数値形式文字列で指定された形式で)出力されます。 :
$ printf '%d\n' '"A' # decimal (doesn't expand quoted vars '"$var')
65
$ printf '%d\n' "'A" # decimal
65
$ printf '%o\n' "'A" # octal
101
$ printf '%x\n' "'A" # Hexadecimal
41
実装間で"'…"
の解釈最初の文字にはいくつかのバリエーションがあることに注意してください(バイトまたは文字。バイトの場合、結果は使用するロケールの影響を受けます)。