文字

文字

私は次のように変換します。整数到着性格そして性格到着整数バッシュから。しかし、私は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

答え1

printf '\101'ここで101、8進数は対応する値でバイトを出力します。

AASCII端末に送信されると、ASCIIおよびAすべてのASCII互換文字セット(ほとんどの最新の文字セットが含まれていますが、一部のIBMシステムではまだ使用されているEBCDIC文字セットを含む)の文字65(8進数101)としてレンダリングされます。

存在する

printf \\$(printf '%03o' $1)

次のように書く必要があります。

printf "\\$(printf '%03o' "$1")"

Bourneなどのシェルでは、パラメータ拡張(例$1:)またはコマンド置換($(...))を引用符で囲まないままにすることは分割+グローブ演算子なので、ここでは必要ありません。

  • printf '%03o' "$1"$1数字を3桁の8進数に変換
  • printf "\\$(...)"\8進数をa(\\二重引用符で囲む)に追加して\渡し、対応するprintfバイト値を出力します。

文字セットが文字ごとに1バイトのロケール(たとえばiso8859-1)、またはマルチバイト文字セットを持つロケールでのみ機能し、値は0から127に対してのみ機能します。

存在するbash

printf '%d\n' "'A"

文字のUnicodeコードポイントを印刷しますA(または少なくともGNUシステムでは、返された値はmbtowc()少なくともUnicodeコードポイントです)。

他のいくつかの実装(スタンドアロンGNUprintfユーティリティを含む)は、文字の最初のバイト値を返します。

これは、ASCIIベースのシステムなどのASCII文字にはA違いはありませんが、他の文字の場合は重要です。たとえば、ギリシャα文字(U + 03B1)は次のようにエンコードされます。

  • iso8859-7のバイト225(標準ギリシャ語のシングルバイト文字セット)
  • UTF-8のバイト206 177(Unixファミリーシステムで最も一般的に使用されるUnicodeエンコーディング)
  • GB18030(Unicodeの公式中国語エンコーディング)のバイト166193です。

Bashはロケールに関係なく(少なくともGNUシステムでは)Unicodeコードポイント(16進数で0x03b1)をprintf '%d\n' "'α"常に出力しますが、他の言語はロケールに応じて225、206、または166を返すことがあります。945α

ASCII文字(または値0〜127)またはすべての文字の文字セット(値0〜255)を使用するロケールの場合、これらのchr合計はord単に互いに逆数であることがわかります。iso8859-1

Unicodeコードポイントを返す場合は、ord()その逆(Unicodeコードポイントに対応する文字印刷)は次のようになります。

chr() {
  printf "\U$(printf %08X "$1")"
}

bash(4.3以上の仮定(\UXXXXXXXX4.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 945chr 206 177

またはロケールで使用してくださいiso8859-7

$ ord α
 225
$ chr 225
α

(945を提供しますが、GNUシステムでifに置き換えると、ord α225を提供できます。)printf/usr/bin/printf

答え2

内部的には、8進数値(例:65)(65 - > 101)をprintf '%03o' $1返します。$1

printf \\$(..)8進値で表される文字を外部に印刷します。

ライン参照man printf:

\NNN 8進値 NNNバイト(1~3桁)

単一文字定数として処理する必要があることを示すように指定する必要があるprintf '%d' "'$1"ため、そうしないと、printfは値が無効な数値であることを示すエラーを生成します。次に、文字定数値を使用して10進形式で印刷します。'$1printf"%d"

答え3

文字

printf \\$(printf '%03o' $1) # 次のようになります...printf "$(printf '\\%03o' "$1")"

1つ目はprintf2番目の出力を使用して文字を生成します。私たちはそれを解読するために逆さまに働かなければなりません。

2番目は、printf整数($1)を8進整数('%03o'形式)に変換するために使用されます。

$ printf '%03o' 12
014
$ printf '%03o' 65
101
$ printf '%03o' 255
377

結果は an\に対応する項目に関連付けられます (シェルの特別な意味を避けるために 2 倍にするか、引用符で囲む必要があります).結果の文字列は\101バイトの8進値として解釈されます。しかし、ただ最大3桁(ほとんどのprintfシェル実装では)このタイプの形式は、シングルバイト0〜255(または8進数で0〜377)で使用されるため、3つの8進数のみが解釈されます。したがって、ほとんどのprintf実装は8進数のみを次に変換します。バイト。バイトがコンソールで使用するロケールのASCII文字を表す場合、その文字が印刷されます。

$ printf \\101\\n
A
$ printf \\377\\n

ロケールの影響を受ける文字(バイトではなく)を印刷するには、次のものが必要です。

  • printfを生成できますマルチバイト使用されるロケールの文字
  • バイトではなく文字が必要な表現形式

たとえば、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"

データ(非形式)文字列は外部引用符を削除し、結果の文字列はで始まります。'a または a で'始まる文字列は"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

"'…"解釈によって多少の違いがあることに注意してください。最初の文字実装間(バイトまたは文字、バイトの場合、結果は使用されるロケールの影響を受けます)

関連情報