Next: , Previous: echo invocation, Up: Printing text   [Contents][Index]


15.2 printf: データを整形して表示する

printf は、テキストを整形して表示する。


書式:

printf format [argument]…

printf は、文字列 format を表示する。 その際、C の ‘printf’ 関数とほとんど同じやり方で、‘%’ 書式指定子と ‘\’ エスケープシーケンスを解釈して、数値や文字列の引数 (上記書式の argument) を整形する。詳細については、次の項目を参照すること。 See printf format directives in The GNU C Library Reference Manual. C の関数との相違点については、以下の箇条書きのとおりである。

シェルの組み込み機能の printf やエイリアスのために、 printf に何の修飾も付けずに対話的に使ったり、スクリプトの中で使ったりすると、 動作がここで述べているものとは違うことがあるかもしれない。 シェルによる干渉を避けるためには、env 経由で printf を起動すればよい (すなわち、env printf … のようにだ)。

引数が浮動小数点数の場合は、小数部の前にはピリオドを置かなければならない。 ただし、表示は、現在のロケールの LC_NUMERIC カテゴリのルールに合わせたものになる。 たとえば、小数点を表す文字がコンマのロケールでは、‘printf %g 3.14’ というコマンドは、‘3,14’ を出力するが、‘printf %g 3,14’ というコマンドはエラーになる。 See Floating point.

printf は、format 中の ‘\ooo’ を (ooo が 1 から 3 桁の 8 進数ならば) 表示すべき 1 バイトを指定している 8 進数と見なす。また、‘\xhh’ を (hh が 1 から 2 桁の 16 進数ならば) 表示すべき 1 文字を指定している 16 進数だと解釈する。 ただし、注意していただきたいが、‘\ooo’ が 255 より大きな 10 進数に相当するときは、printf は 9 ビット目を無視する。 従って、たとえば、‘printf '\400'’ は ‘printf '\0'’ と同じである。

printf は、ISO C 99 で導入された 2 種類のキャラクタ・シンタクス (訳注: 要するに、コードによる文字の指定法) を解釈することができる。 一つは、Unicode (ISO/IEC 10646) の文字を 16 ビットで表すための ‘\u’ であり、4 桁の 16 進数 hhhh で指定する。もう一つは、Unicode の文字を 32 ビットで表すための ‘\U’ で、こちらは 8 桁の 16 進数 hhhhhhhh で指定する。printf は Unicode の文字を出力するに当たって、 LC_CTYPE のロケールに従う。なお、U+0000…U+009F と U+D800…U+DFFF の範囲にある Unicode の文字は、U+0024 ($), U+0040 (@), U+0060 (‘) を除いて、このシンタクスでは指定することができない。

\u’ や ‘\U’ を処理するには、フル装備の iconv の能力が必要である。 glibc 2.2 以降を採用しているシステムでは、そうした能力は使えるようになっている。 coreutils パッケージをインストールする前に、libiconv をインストールしている場合も同様だ。どちらにも当てはまらない場合は、‘\u’ や ‘\U’ は、変換されずに、そのままの形で表示される。

オプションとして指定できるのは、単独の --help--version だけである。 See Common options. オプションはオペランドの前に置かなければならない。

Unicode のキャラクタ・シンタクスを使えば、 ロケールに影響されない方法で文字列を書くことができて、便利である。 たとえば、次のようにすれば、

$ env printf '\u20AC 14.95'

ユーロ通貨記号を含む文字列が、ユーロ記号をサポートするすべてのロケール (ISO-8859-15, UTF-8 など) で正しく出力されることになる。同様に、

$ env printf '\u4e2d\u6587'

とすれば、漢字の文字列が、すべての中国語のロケール (GB2312, BIG5, UTF-8 など) で正しく表示される。

上記の例では、printf コマンドを env 経由で呼び出していることに注目していただきたい。 これは、シェルのエイリアスや組み込み関数ではなく、 シェルのサーチパスを使って見つけたプログラムを、確実に実行するためである。

文字列がもっと長い場合でも、各文字に対応する 16 進数コードを一つ一つ捜す必要はない。 ASCII 文字に \u エスケープ・シーケンスを混ぜる書き方は、JAVA のソースファイルで使用されるエンコーディング (JAVA source file encoding) としても知られているが、GNU の recode コマンド 3.5c 以降を使用すれば、任意の文字列をこのエンコーディングに変換することができるのだ。 以下に示すのは、1 個の短文を、ロケールに影響されずにその短文を出力するシェルスクリプトに変換する方法である。

$ LC_CTYPE=zh_TW.big5 /usr/local/bin/printf \
    '\u4e2d\u6587\n' > sample.txt
  #
  # 訳注: もちろん、漢字入力の可能な LANG=zh_TW.big5 (あるいは、
  #       LANG=ja_JP.eucJP) の環境なら、コマンドラインで直接
  #       printf '中文\n' と打ち込んでもよい。その方が、
  #       「各文字に対応する 16 進数コードを一つ一つ捜す必要はない」
  #       という上記の説明に、例としてはふさわしいだろう。
  #       LANG=ja_JP.eucJP の場合、下のコマンドは、当然ながら、
  #       recode eucJP..JAVA になる。
  #
$ recode BIG5..JAVA < sample.txt \
    | sed -e "s|^|/usr/local/bin/printf '|" -e "s|$|\\\\n'|" \
    > sample.sh

終了ステータス 0 は成功を示し、0 以外の値は失敗を示す。


Next: , Previous: echo invocation, Up: Printing text   [Contents][Index]