ASCII 文字の一覧を Bash で表示してみました

前回、改行コードを扱ったときに、 Bash で CR の改行コードをファイルに書き込むことを調べたので、書いておきます。

結果だけ知りたい場合は、 ASCII 文字の一覧をご参照ください。

環境

  • Ubuntu 16.04 LTS

echo

echo コマンドでできるかな、と思って man echo を調べてみました。

-n do not output the trailing newline

-e enable interpretation of backslash escapes

If -e is in effect, the following sequences are recognized:

\n new line

\r carriage return

man echo

$ echo -ne '\r' | od -t a
0000000  cr
0000001

CR はエスケープ文字で \r のように記述すると出力できます。 バックスラッシュのエスケープ文字を有効にするには -e のオプションをつけるようです。

-n オプションをつけると出力の最後で改行しないようです。

octal value

\0NNN byte with octal value NNN (1 to 3 digits)

man echo

今回は、 ASCII 文字の一覧を表示したいので、コードで文字を指定する方法を調べてみました。 8 進数で指定する場合は、 \0NNN のように記述するようです。

$ echo -e '\0101'
A

8 進数の 101 は A なので、 A と表示されました。

$ echo -ne '\015' | od -t a
0000000  cr
0000001

8 進数の 15 は CR なので、 CR と表示されました。

hexadecimal value

\xHH byte with hexadecimal value HH (1 to 2 digits)

man echo

16 進数で指定する場合は、 \xHH のように記述するようです。

$ echo -e '\x42'
B

16 進数の 42 は B なので、 B と表示されました。

$ echo -ne '\x0d' | od -t a
0000000  cr
0000001

16 進数の 0d は CR なので、 CR と表示されました。

man echo を見ると、 10 進数では指定できないようで、 10 進数を 8 進数か 16 進数に変換する必要があるようでした。

printf

Convert a decimal number to Hex

printf "0x%X\n " 15
# 0xF

Convert a decimal number to Octal

printf "0%o\n " 8
# 010

printf Man Page - Bash - SS64.com

調べてみると、 10 進数から 8 進数や 16 進数に変換するには、 printf を使うのが多いみたいでした。 それ以外だと簡単にはできないのかな。

WSL の Ubuntu の man printf には Convert a decimal number to Hex や Convert a decimal number to Octal の記載がなかったので、ウェブサイトから引用しました。

Convert a decimal number to Octal

10 進数から 8 進数にしてみます。

$ printf "0%o\n " 8
010

8 進数にできました。 10 進数の 8 は 8 進数の 10 です。

Convert a decimal number to Hex

10 進数から 16 進数にしてみます。

$ printf "0x%X\n " 15
0xF

16 進数にできました。 10 進数の 15 は 16 進数の F です。

Command substitution

10 進数から 8 進数や 16 進数にした結果を別のコマンドの入力にしたかったのですが、 echoprintf は標準入力から入力できないみたいでした。

Command substitution allows the output of a command to replace the command itself. Command substitution occurs when a command is enclosed as follows:

$(command)

or

`command`

3.5.4 Command Substitution

$(command) は Command substitution というそうです。 コマンドの結果を返して変数に代入するときとかに使うようです。 `command` と記述しても同じ意味になるようです。

Command substitution を使って、 command "$(printf ...)" のようにしてみます。

printf byte

echo でもコードから ASCII 文字を出力することができましたが、 printf でもできるみたいでした。 10 進数から 8 進数や 16 進数にするのに printf を使うので、統一して printf で ASCII 文字を出力しようと思います。

printf octal value

FORMAT controls the output as in C printf. Interpreted sequences are:

\NNN byte with octal value NNN (1 to 3 digits)

man printf

printf で 8 進数から ASCII 文字を表示するには、 \NNN という書式を設定すればいいみたいです。 NNN のところを 10 進数で指定して、 8 進数に変換した結果を渡したいので、 Command substitution も使って、次のように記述しました。

$ printf "$(printf '\\%o' 65)"
A

内側の printf で 10 進数から 8 進数に変換した結果を返しました。 書式の先頭に \\ をつけましたので、 \NNN の結果を返すことになります。

外側の printf で 8 進数のコードから ASCII 文字を表示することになります。

10 進数の 65 は A なので、 A と表示されました。

printf hexadecimal value

FORMAT controls the output as in C printf. Interpreted sequences are:

\xHH byte with hexadecimal value HH (1 to 2 digits)

man printf

printf で 16 進数から ASCII 文字を表示するには、 \xHH という書式を設定すればいいみたいです。 HH のところを 10 進数で指定して、 16 進数に変換した結果を渡したいので、 Command substitution も使って、次のように記述しました。

$ printf "$(printf '\\x%x' 66)"
B

10 進数の 66 は B なので、 B と表示されました。

'\\x%x' のところ、ダブルクォーテーションだったり、 \ が 1 つだったりするとエラーになりました。 シングルクォーテーションで、 \\ のようにしておく必要があるようでした。

$ printf "\\x%x" 65
-bash: printf: missing hex digit for \x
\x41
$ printf '\x%x' 65
-bash: printf: missing hex digit for \x
\x41

たぶん、 printf は引数を 1 つだけとって、 \xHH のように記述することもできるので、

$ printf "\x41"
A

%x の書式に引数の値を入れるよりも先に、 \xHH の解釈をしようとしてエラーになってしまっているように見えました。

Brace Expansion

1 つの 10 進数から ASCII 文字を表示するところまでできました。 一覧を表示したいので、これを繰り返し処理してみたいと思います。

ASCIIとは、アルファベットや数字、記号などを収録した文字コードの一つ。最も基本的な文字コードとして世界的に普及している。7ビットの整数(0~127)で表現され、ラテンアルファベット(ローマ字)、数字、記号、空白文字、制御文字など128文字を収録している。

現代のコンピュータのほとんどは1バイト(8ビット)を単位としてデータを扱うため、1文字を7ビットではなく1バイトで表すのが都合がよく、その際、128から255までの128文字分はASCIIでは規定されていない領域となる。

ASCII(アスキーコード)とは - IT用語辞典

ASCII 文字は 10 進数で表現すると 0 から 127 までになります。 まず、 10 進数で 0 から 127 を表示してみます。

Brace expansion is a mechanism by which arbitrary strings may be generated.

…略…

Brace expansions may be nested. The results of each expanded string are not sorted; left to right order is preserved. For example,

bash$ echo a{d,c,b}e
ade ace abe

A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters, and incr, an optional increment, is an integer.

3.5.1 Brace Expansion

ブレース展開というものがあるようです。 引用の例ではカンマで区切られた文字列を記述していますが、シーケンス式で連番を返すこともできるようです。

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

英字もいけます。

$ echo {A..E}
A B C D E

printf もいけます。

$ printf "%o\n" {1..10}
1
2
3
…略…
7
10
11
12

ここでは 8 進数で表示してみました。 printf の引数でブレース展開をして、繰り返し printf コマンドを実行できるのは初めて知りました。

最初、 forseq を試しましたが、 Brace Expansion が便利そうでした。 参考までに、 forseq を使うと次のようになりました。

$ for i in $(seq 65 90); do printf "%x\n" $i; done;
41
42
43
…略…
58
59
5a

seq だけだと次のようになりました。

$ seq 65 90
65
66
67
…略…
88
89
90

forseqprintf と組み合わせて使おうとすると、少し面倒になりそうでしたのでやめました。

ASCII 文字の一覧

8 進数

10 進数から 8 進数にして、 ASCII 文字を表示してみます。

$ printf "$(printf '\\%o' {0..127})" | od -t a
0000000 nul soh stx etx eot enq ack bel  bs  ht  nl  vt  ff  cr  so  si
0000020 dle dc1 dc2 dc3 dc4 nak syn etb can  em sub esc  fs  gs  rs  us
0000040  sp   !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
0000060   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
0000100   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
0000120   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
0000140   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
0000160   p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ del
0000200

だぶんできたみたいです。 制御文字はそのままだと確認できないので、 od -t a にパイプで渡しました。

16 進数

次は、 10 進数から 16 進数にして、 ASCII 文字を表示してみます。

$ printf "$(printf '\\x%x' {0..127})" | od -t a
0000000 nul soh stx etx eot enq ack bel  bs  ht  nl  vt  ff  cr  so  si
0000020 dle dc1 dc2 dc3 dc4 nak syn etb can  em sub esc  fs  gs  rs  us
0000040  sp   !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
0000060   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
0000100   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
0000120   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
0000140   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
0000160   p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ del
0000200

だぶんできたみたいです。

終わり

最初、 for を使ってみたのですが、この記事を書きながら調べていて、ブレース展開でもできることがわかりました。 調べたらもっとシンプルにできるのかな。

参考

Bash のマニュアルってないのかな、と思っていたのですが、 GNU のがあったみたいでした。

記号とか検索しづらいので、こういうマニュアルはありがたいです。