LinuxでBashprintfコマンドを使用する方法
公開: 2022-06-25
Bash printfコマンドを使用すると、 echoコマンドが提供するよりも細かい制御とより多くのフォーマットオプションを使用してLinuxターミナルウィンドウに書き込むことができます。 printfの奇妙な癖でさえも役立つことがあります。
ターミナルへの書き込み
これは、プログラムとの対話の最も基本的な部分の1つです。 プログラムが画面に何かを書き込み、あなたがそれを読みます。 Unixから派生したLinuxでサポートされているコマンドラインプログラムの規則が可能な限り簡潔であることを考慮しても、多くの場合、問題が発生した場合にのみ端末に書き込みます。 何が起こっているのか、これから起こるのか、あるいは起こったばかりなのかをユーザーに伝えることは、プログラミングの基本的な要素です。
Bashシェルには、ターミナルウィンドウにテキストを書き込むことができるechoコマンドがあります。 変数を処理し、それらが文字列に含まれている場合はその値を表示でき、スクリプトまたはコマンドラインで使用できます。 では、なぜprintfが存在するのでしょうか。 echoはテキストを書くことをカバーしていませんか? ええと、 printfは、ターミナルウィンドウに文字列を書き込むという単純な行為を超えた機能を提供します。 それはあなたが非常に柔軟に出力をフォーマットすることを可能にします、そしてそれは他のトリックも持っています。
Bash printfコマンドは、C言語のprintf関数をモデルにしていますが、違いがあります。 Cを知っている場合は、それらの違いに注意する必要があります。
基本的な文字列を書く
ターミナルに文字列を書き込むときのechoとprintfの違いを見てみましょう。
ここにエコーはいくつかの言葉です
ここのprintfはいくつかの言葉です

echoコマンドはすべての単語を出力しますが、 printfは最初の単語のみを出力します。 また、 printfによって印刷される改行はありません。 出力は、コマンドプロンプトに直接表示されます。 ただし、まず最初に、 printfをすべての単語に作用させるには、それらを引用する必要があります。
ここにエコーはいくつかの言葉です
printf「ここにいくつかの単語があります」

それがいいです。 すべての単語が印刷されていますが、まだ改行がありません。 これは、 printfでは、要求した場合にのみ新しい行を取得するためです。 それは苦痛に思えるかもしれませんが、それを含めるかどうかを決めることができます。 printfに改行を発行させるには、文字列に「 \n 」を含める必要があります。 これは「改行」エスケープシーケンスです。
ここにエコーはいくつかの言葉です
printf"ここにいくつかの単語があります\n"

改行を使用する場合と使用しない場合があります。 これは、一方のprintfステートメントが新しい行を使用し、もう一方が使用しない場合です。
printf"ハウツー"&&printf"オタク\n"

最初のprintfは新しい行を印刷しないため、2番目のprintfからの出力は、「ハウツー」の直後の同じ行に配置されます。 2番目のprintfは、 \nを使用して新しい行を印刷します。 これにより、コマンドプロンプトが印刷されたテキストの下の行に表示されます。
関連: LinuxBashスクリプトでファイルを1行ずつ処理する方法
その他のエスケープ文字
使用できるエスケープ文字をさらにいくつか示します。 「 \n 」の動作はすでにご覧になっています。
- \ n :新しい行に移動します。
- \ r :キャリッジリターンを出力します。 これにより、出力カーソルが現在の行の先頭に戻ります。
- \ t :タブ文字を出力します。
- \ v :垂直タブスペースを印刷します。
- \\ :円記号を出力します。
- \” :引用文字を出力します。
- \ b :バックスペース文字を出力します。
キャリッジリターンエスケープ文字は、カーソルを現在の行の先頭に戻します。
printf"蜂蜜はすべての悪の根源です\rお金\n"

printfコマンドは、入力を左から右に処理します。 printfが「 \r 」エスケープ文字に遭遇するまで、文字列は通常のテキストとして出力されます。 出力カーソルが現在の行の先頭に戻ります。
文字列の処理は、「 \r 」文字のすぐ後ろの文字から再開されます。 余りを処理すると、 printfは「Money」を出力し、「Honey」という単語を上書きします。
引用符「 " 」は文字列を引用するために使用され、バックスラッシュ「 \ 」文字はエスケープシーケンスを示します。これらの文字を印刷する場合は、バックスラッシュでエスケープする必要があります。これにより、 printfは文字列として扱うように指示されます。
printf"これは\tTabであり、これは引用符\"であり、この\\は円記号です\ n "

変数の使用
printfで変数を使用することは、 echoで変数を使用することと非常に似ています。 この環境変数のような変数を含めるには、通常どおり、その前にドル記号「 $ 」を付けます。
printf "ホームディレクトリ:$ HOME \ n"

関連: Bashで変数を操作する方法
文字列のフォーマット
フォーマット文字列は、出力のフォーマットを定義する文字列です。 操作するフォーマット文字列の引数として、テキストやその他の値を指定します。
フォーマット文字列には、テキスト、エスケープシーケンス、およびフォーマット指定子を含めることができます。 フォーマット指定子は、文字列、整数、文字など、予想される引数のタイプをprintfに通知します。
これらは最も一般的なフォーマット指定子です。 それらはすべてパーセント「 % 」記号で始まります。 パーセント記号を印刷するには、2つのパーセント記号を一緒に「 %% 」として使用します。
- %s :文字列を出力します。
- %c :1文字を出力します。
- %d :整数を出力します。
- %f :浮動小数点数を出力します。
- %u :符号なし整数を出力します。
- %o :値を8進数で出力します。
- %x :値を16進数で小文字で出力します。
- %X :値を16進数で大文字で出力します。
- %e :浮動小数点数を科学的記数法で小文字で出力します。
- %E :浮動小数点数を科学的記数法で大文字で出力します。
- %% :パーセント「%」記号を出力します。
printf "ハウツー%s \n""オタク"
printf "%s%s%s \ n" "How" "-To" "Geek"

最初のコマンドのフォーマット文字列には、独自のテキストが含まれています。 文字列「Geek」を引数としてprintfに渡します。 これは、「 %s 」フォーマット指定子と照合され、印刷されます。 フォーマット文字列と引数文字列の間にはスペースがあることに注意してください。 Cでは、それらを区切るためにコンマが必要ですが、Bashバージョンのprintfではスペースを使用するだけで十分です。
2番目のフォーマット文字列には、フォーマット指定子と改行エスケープシーケンスのみが含まれます。 3つの文字列引数は、「 %s 」形式指定子のそれぞれによって順番に使用されます。 繰り返しますが、Cでは、各引数の間にコンマを入れる必要がありますが、 printfではそのことを忘れさせてくれます。
さまざまなタイプの引数を出力するには、適切なフォーマット指定子を使用するだけです。 これは、 printfを使用して構築された簡単な数値変換ルーチンです。 値15を、10進数、8進数、および16進数の表記で出力します。

printf "Dec:%d \ nOct:%o \ nHex:%x \ n" 15 15 15

例が乱雑にならないように、少し後ろにトリミングしてみましょう。
printf "Hex:%x \ n" 15

私たちのほとんどは、16進値を大文字で表示し、0x10未満の値を先行ゼロで出力することに慣れています。 これは、大文字の16進形式指定子「 %X 」を使用し、パーセント記号「 % 」と「 X 」文字の間に幅指定子を配置することで実現できます。
これは、引数を出力するフィールドの幅をprintfに指示します。フィールドにはスペースが埋め込まれます。 この形式では、2桁の値がパディングなしで印刷されます。
printf "Hex:%2X \ n" 15

これで、先頭にスペースが印刷された大文字の値が取得されます。 2つの前にゼロを置くことで、 printfがスペースの代わりにゼロでフィールドをパディングするようにすることができます。
printf "Hex:%02X \ n" 15

精度指定子を使用すると、出力に含める小数点の数を設定できます。
printf "浮動小数点:%08.3f \ n" 9.243546

これにより、出力が適切に調整された結果のテーブルを簡単に作成できます。 この次のコマンドは、 printfのもう1つの癖も示しています。 フォーマット指定子よりも多くの引数がある場合、すべての引数が使い果たされるまで、引数はバッチでフォーマット文字列にフィードされます。 一度に処理されるバッチのサイズは、フォーマット文字列内のフォーマット指定子の数です。 Cでは、 printf関数呼び出しの余分な引数は無視されます。
printf "Float:%8.3f \ n" 9.243546 23.665 8.0021

文字列で幅と精度の指定子を使用することもできます。 このコマンドは、10文字幅のフィールドに文字列を出力します。
printf "%10s%d \n""コート"7"靴"22"傘"3

デフォルトでは、値はフィールドで右寄せされます。 それらを左揃えにするには、パーセント記号「 % 」の直後にマイナス記号「 - 」を使用します。
printf "%-10s%d""コート"7"靴"22"傘"3

精度指定子を使用して、印刷される最大文字数を設定できます。 幅フィールドの制限を示すために、コロン文字「 : 」を使用しています。 「傘」という言葉がどのように切り捨てられるかではありません。
printf ":%10.6s:\n""コート""靴""傘"
printf ":%-10.6s:\n""コート""靴""傘"

幅指定子は、引数として渡すこともできます。 数値指定子の代わりにアスタリスク「 * 」を使用し、幅を整数引数として渡します。
printf "%* s \ n"20"右端"12"中央"5"左端"

その他の秘訣と癖
フォーマット文字列内のフォーマット指定子は、コマンドラインで通常の引数として提供されているか、式の出力として生成されているかに関係なく、適切なタイプの値で機能します。
これにより、2つの数値の合計が出力されます。
printf "23 + 32 =%d \ n" $((23 + 32))

このコマンドは、現在の作業ディレクトリ内のディレクトリの数を出力します。
printf "%d個のディレクトリがあります\ n" $(ls -d * / | wc -l)

このprintfコマンドは、別のコマンドの呼び出しから返された文字列を出力します。
printf "現在のユーザー:%s \ n" $(whoami)

文字列フォーマット指定子「 %s 」に引数が指定されていない場合、 printfは何も出力しません。
printf "1:%s 2:%s \n""アルファ"

文字列形式指定子「 %s 」に誤って数値が指定された場合、文字列であるかのように出力され、文句はありません。 C printfでこれを試さないでください—非常に悪いことが起こります。 プログラムがクラッシュする可能性があります。 しかし、 printfは文句を言わずにそれを処理します。
printf "One:%s two:%s \ n" "Alpha" 777

整数形式指定子「 %d 」が引数を受け取らない場合、ゼロを出力します。
printf "整数:%d \ n"

整数フォーマット指定子「 %d 」が誤って文字列引数を受け取った場合、Bashはエラーメッセージを出力し、 printfはゼロを出力します。
printf "整数:%d \n""セブン"

厄介な記号は、Unicode番号または「コードポイント」を使用して生成できます。 これらは、文字「u」とそれに続くUnicode値を使用してエスケープされます。
printf "ユーロ記号:\ u20AC \ n"

引数文字列にエスケープシーケンスを含めるには、「 %s 」文字列フォーマット指定子ではなく、フォーマット文字列に「 %b 」フォーマット指定子を使用する必要があります。
printf "%s" "\ u20AC \ n"
printf "%b" "\ u20AC \ n"

最初のprintfステートメントはUnicode値を処理せず、改行エスケープシーケンスを認識しません。 2番目のprintfステートメントは、「 %b 」フォーマット指定子を使用します。 これにより、Unicode文字が正しく処理され、新しい行が出力されます。
関連: ANSIやUnicodeのような文字エンコードとは何ですか?また、それらはどのように異なりますか?
コース用の馬
場合によっては、テキストをターミナルウィンドウにechoするだけで済みます。 ただし、ポジショニングとフォーマットを適用する必要がある場合は、 printfがその仕事に適したツールです。
printf "%b" "Tha-" "tha-""tha-""それはすべての人々です。\n"

