Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

【実例付き】Bash/Shellのprintfコマンドの使い方を徹底解説

この記事では、LinuxのBash/Shellでprintfコマンドを使うための実用的な例を紹介します。

printfコマンドは、echoコマンドと同じようにテキストを出力できますが、出力フォーマットをより細かく制御できる点が大きな違いです。

独自の整形済みテキスト出力を生成するのに便利なツールです。特に、変数をテキストに埋め込む、改行を含める、テキストを揃えて整形する、変換した値を表示するといった場面で活躍します。

printfの基本構文

printfコマンドは以下の構文を持ちます。

printf [-v var] format [arguments]...

各要素の意味は次のとおりです。

  • -vオプションを指定すると、結果を画面に出力する代わりに変数varに格納します
  • format(書式指定)は、次の3種類の値を組み合わせた文字列です。
    • そのまま出力される通常の文字
    • 出力前に解釈されるバックスラッシュによるエスケープ文字
    • 対応する引数に置き換えられる変換指定子(変数のようなものと考えると分かりやすい)
  • arguments(引数)はformatに渡され、定義された変換指定子の中で使用されます。
    • 引数の数が変換指定子より多い場合、すべての引数が消費されるまでformat文字列が繰り返し適用されます
    • 逆に引数が足りない場合、数値指定子は0に、文字列指定子は空(null)に設定されます

printfのエスケープ文字・変換指定子・フラグ

printfには非常に多くのオプションが用意されており、多彩な方法でテキストを整形できます。以下の例で実践的な使い方を見ていきましょう。

ここですべてのオプションを列挙する代わりに、次のコマンドでシステムにインストールされているprintfの完全なマニュアルを確認できます。

man printf

printfのBash/Shell実例集

それでは、これらの機能が実際に何に役立つのか、具体的な例を見ていきましょう。

数値を四捨五入して表示する

まずはシンプルなシナリオから。数値を小数点以下2桁に整形して表示したい場合は次のようにします。

printf "%.2f" 4.21423557

出力結果:

4.21

指定した書式%.2fにより、printfは数値を小数点以下2桁に整形します。これは書式内の.(ピリオド)で表される精度(precision)ディレクティブによるものです。

このとき、数値は切り捨てられるのではなく、指定桁数に丸め(四捨五入)られる点に注意してください。浮動小数点数の丸めには癖があるため、出力結果は必ず確認しましょう!

丸め処理の奇妙な挙動

この奇妙な挙動を説明するために、次の例を見てください。

printf "%.2f" 4.215

4.22になるはずですよね?ところが違います。zshのprintf実装では、次のように丸められます。

4.21

数値が実際に丸められていることを確認するため、別の値も試してみましょう。

printf "%.2f" 4.216

結果はこうなります。

4.22

…ということは、printfに渡された数値は確かに丸め処理されています。

では、なぜ4.215の丸め結果が期待と異なるのでしょうか?簡単に言えば、この値が浮動小数点数であることが原因です。表示上の値と、コンピュータが内部計算で使用している値との間に微妙な不一致があり、それが誤差として現れます。

回避策も存在しますが、本記事の範囲を超えるため、別の記事で詳しく取り上げます。

値の変換(10進数・16進数・8進数)

よくあるケースとして、他のプログラムやスクリプトから受け取った数値を別の形式で表示したい場面があります。printfは変換指定構文を使って、これを簡単に実現できます。

printf "Decimal: %d\nHexadecimal: %x\nOctal: %o\n" 64 64 64

出力結果:

Decimal: 64
Hexadecimal: 40
Octal: 100

数値64がフォーマッタに3回渡され、それぞれ10進数・16進数・8進数という3つの異なる形式で表示されています。

見やすい整形済み出力を作る

次の例では、printfを使って整形された表を出力します。コメントで順に説明しているので、処理の流れが分かりやすいはずです。

#/bin/bash

# ヘッダーテキスト用のフォーマットを定義
# 改行(\n)に続き、左揃え15文字の文字列(%-15s)、右揃え15文字の文字列(%15s)、
# 最後に右揃え10文字の文字列(%10s)と改行を指定
header_format="\n %-15s %15s %10s\n"

# 各行のデータ用のフォーマットを定義
# 最初の2つはヘッダーと同じだが、最後は小数点以下2桁の浮動小数点数(%11.2f)
row_format=" %-15s %15s %11.2f\n"

# printfコマンドでヘッダーを出力
# フォーマットを指定し、表の列名を引数として渡す
# printfはheader_formatに基づき、引数の値を指定どおりに整形して挿入し、出力する
printf "$header_format" "CAR BRAND" "COLOUR" "TOP SPEED"

# 表ヘッダーの下に横線を出力
# ブレース展開(波括弧)はシェルスクリプトのショートカットで、
# 1から50までの各数値についてprintfを実行し、イコール記号を50回繰り返して線を作る
printf '=%.0s' {1..50}

# row_formatを使って各行のデータを出力
# 各行(バックスラッシュ+改行で区切る)には車のブランド・色・最高速度の3つの値を渡す
# スペースを含む値は引用符で囲む必要がある。値はスペース区切りとみなされるため、
# 囲まないとprintfが値の境界を正しく判別できない
printf "$row_format" \
Toyota Blue 100 \
Ford "Light Green" 78.3875 \
"General Motors" Purple 15.96

このスクリプトを実行すると、次のような出力が得られます。

CAR BRAND                COLOUR  TOP SPEED
==================================================
Toyota                     Blue      100.00
Ford                Light Green       78.39
General Motors           Purple       15.96

printfがデータをどのように整形したか、よく観察してみてください。ヘッダーと各行で特定の文字数が指定されているため、テキストがきれいに揃っています。最高速度は小数点以下2桁に整形され、適切な位置に配置されています。最初の列以外は右揃えになっていますね。

わずかな構文だけで、読みにくかったデータが有用な情報へと生まれ変わりました。

応用の可能性は無限大

printfの使い道は、自分で見つけていくものです。スクリプト向けの見栄えのよいメニューを持つコマンドラインインターフェースの構築や、データベースクエリ結果の表形式での表示など、アイデア次第でさまざまな用途に活用できます。無整形のテキストを画面に垂れ流すのではなく、洗練された見た目のシェルスクリプトで人を感心させたいなら、ぜひ習得しておきたい強力なツールです。

さらに、printfはLinuxの他のテキスト処理コマンドと組み合わせることもできるので、可能性はさらに広がります。

  1. Bashシェル関数入門:実用的な6つのサンプル例で学ぶチュートリアル

    Bashシェル関数とは、複数のUNIX/Linuxコマンドをひとつの名前でグループ化し、後からまとめて実行できるようにする仕組みです。Bashシェル関数は通常のUnixコマンドと同じように呼び出すことができ、現在のシェルコンテキスト内で実行されるため、解釈用の新しいプロセスを生成する必要がありません。bashのエイリアス(alias)と関数はどちらも、長いコマンドや複雑なコマンドに対するショートカットを定義するのに役立ちます。しかし、エイリアスでは制御フローや引数の扱いなど、関数ならではの高度な処理を行うことはできません。本記事では、その違いも含めて詳しく解説していきます。この記事は、進行中の

  2. 実用的な5つの例で学ぶBashスクリプト入門チュートリアル

    Unix SedやUnix Awkシリーズと同様に、本シリーズではBashスクリプティングに関する記事を複数回にわたって公開します。実用的なサンプルを交えながら、Bashスクリプティングのテクニックを幅広く解説していきます。 シェルとは、ユーザーが入力したコマンドを解釈して実行するプログラムです。コマンドはユーザーが直接入力するか、「シェルスクリプト」と呼ばれるファイルから読み込まれます。 ユーザーからの入力を直接読み取る場合、そのシェルは対話型(インタラクティブ)シェルと呼ばれます。 一方、ファイルからコマンドを読み込んで実行する場合は非対話型(ノンインタラクティブ)シェルと呼ばれます。この