順番に読み進めながら学べます

出力とレポート — printf と here-doc で書き出す

この記事は、基礎コマンドからシェルスクリプトまでLinuxの実践的なスキルを1からマスターする「Linux入門講座の一部」です。
printf '%s\t%s\n' で列をそろえ、> >> で結果を追記し2> でエラーを別ファイルへ分け、here-docテンプレートに $(wc -l)を埋め込んだ集計レポートを作る流れを、図解と端末で実習します。

整形して出力する — printf と出力先の振り分け

スクリプトの結果を読みやすく出すには、文字列をそのまま出すechoと、書式を指定して桁や区切りをそろえるprintfを使い分けます。

変数の値を 1 行そのまま出すだけならecho "$v"で十分です。

printf '%s\t%s\n' name ageのように書くと、%sの位置に引数が順に入り、\tはタブ、\nは改行になります。

echoと違いprintfは自動で改行しないので、行末に必ず\nを書きます。

コマンドの出力には標準出力と標準エラーの2系統があります。

> fileは標準出力をファイルへ上書き、>> fileは末尾へ追記、2> fileは標準エラーだけを別ファイルへ振り分けます。

正常な結果はレポートに、エラーは別ファイルに分けると、後から原因を追いやすくなります

vi fmt.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   printf '%s\t%s\n' name age      # 見出しをタブ区切りで
#   printf '%s\t%s\n' alice 30      # データ行をそろえて出力
#   echo "done" >> fmt.log           # ログには追記
chmod +x fmt.sh
./fmt.sh
出力先の振り分け
通常の結果標準出力> 上書き / >> 追記エラー標準エラー2> err.logレポートへエラーは別ファイルへ
通常の結果は>(上書き)/>>(追記)でレポートへ、エラーは2>で別ファイルへ分けます。
書き方意味
echo "$v"変数や文字列をそのまま出力するecho "$name"
printf "%s\t%s\n" a b書式付きで出力する(タブ区切り・改行を明示)printf '%s\t%s\n' name age
> f標準出力をファイルへ上書きするecho line > report.txt
>> f標準出力をファイルへ追記するecho more >> report.txt
2> err標準エラーだけを別ファイルへ分けるcat missing 2> err.log

整形出力と出力先の振り分けを行うスクリプトを作って実行します。

vi format.shformat.shを開き、iで挿入モードに入って整形出力とレポート書き出しの処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x format.shで実行権を付与してください。

./format.shで実行し、画面の整形出力を確認してください。

cat table.txtで書き出されたレポートの内容を確認してください。(正しく実行できれば解説が表示されます)

Linux console
0 / 4 実行済み
Loading Linux Terminal...

集計レポートを1ファイルにまとめる — here-doc とコマンド置換

決まった体裁のレポートは here-doc で雛形を書き、その中にコマンドの結果を埋め込みます

cat > report.txt <<EOF … EOFの間に書いた行はそのままファイルになり、$(...)を書くと実行結果がその位置に展開されます。

クォートしない<<EOFでは変数とコマンド置換が展開され、<<'EOF'(シングルクォート付き)では一切展開されず字面のまま出ます。

件数や合計などの集計値はwc -lgrep -cなどをコマンド置換で取り込みます。

レポートを書き終えたら処理が成功したかどうかをexitのコードで呼び出し元へ返します。

exit 0なら成功、exit 1なら何か問題があったことを意味し、後続の&&や CI から判定できます。

vi summary.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   log=access.log
#   lines=$(wc -l < "$log")          # 行数を集計
#   cat > summary.txt <<REPORT       # テンプレートに値を埋め込む
#   --- access summary ---
#   total lines: $lines
#   REPORT
#   echo "summary.txt created"
#   exit 0
chmod +x summary.sh
here-doc に集計結果を埋め込む
access.log$(wc -l) で数えるtotal = 5<<EOF … EOF$total を埋め込むreport.txt 完成集計するテンプレートに埋め込む
$(wc -l)で集計した値を here-doc テンプレートの$(...)位置に埋め込み、1 つのレポートにまとめます。
書き方意味
<<EOF … EOF変数・コマンド置換を展開する here-doccat <<EOF > t.txt
<<'EOF' … EOF一切展開せず字面のまま出す here-doccat <<'EOF' > t.txt
$(wc -l < f)集計値をコマンド置換で取り込むn=$(wc -l < access.log)
exit 0 / exit 1成功・失敗の終了コードを返すexit 0

ログから件数を集計し、here-doc のテンプレートに埋め込んでレポートを 1 ファイルにまとめます。

① 素材ログをprintf 'GET /a 200\nGET /b 404\nGET /c 200\nGET /d 500\nGET /e 200\n' > access.logで作成してください。

vi report.shreport.shを開き、iで挿入モードに入って、件数をコマンド置換で集計し here-doc のテンプレートに埋め込む処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x report.shで実行権を付与してください。

./report.shで実行し、生成されたreport.txtの集計値とテンプレートをcat report.txtで確認してください。

Linux console
0 / 3 実行済み
Loading Linux Terminal...

標準出力とエラーを別ファイルへ分ける

1 つのコマンドが正常な結果とエラーを同時に出すとき、> ok.txt 2> err.txtのように書くと、標準出力はok.txt、標準エラーはerr.txtへ分けて保存できます。

後から「結果」と「問題」を別々に確認できるので、運用スクリプトのログ設計でよく使う形です。

ls /etc /no_such_dir > ok.txt 2> err.txt   # 一覧は ok.txt、エラーは err.txt へ
cat ok.txt                                  # /etc の一覧(標準出力)
cat err.txt                                 # /no_such_dir のエラー(標準エラー)
1つのコマンドの2系統を分ける
ls /etc /no_suchok.txt(結果)err.txt(問題)> 標準出力2> 標準エラー
1 つのコマンドの標準出力は> ok.txt、標準エラーは2> err.txtへ同時に分けて保存できます。
書き方意味
cmd > ok 2> err標準出力と標準エラーを同時に別ファイルへls /etc > ok.txt 2> err.txt
echo "…" 1>&2メッセージを標準エラー側へ出すecho failed 1>&2

1 つのコマンドの標準出力とエラーを別々のファイルへ振り分けるスクリプトを作って実行します。

vi split.shsplit.shを開き、iで挿入モードに入って標準出力とエラーを別ファイルへ振り分ける処理を書き、Esc:wqで保存してください(書く内容は解答パネルからコピーして貼り付けられます)。

chmod +x split.shで実行権を付与してください。

./split.shで実行し、画面に出るok.txterr.txtの行数を確認してください。

cat ok.txtで標準出力の内容、cat err.txtでエラーの内容をそれぞれ確認してください。

Linux console
0 / 5 実行済み
Loading Linux Terminal...
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1printf '%s\t%s\n' a b\t\nは何を表しますか?

Q2コマンドの標準エラーだけを別ファイルへ振り分ける書き方はどれですか?

Q3here-doc のテンプレート内で$(...)の実行結果を埋め込みたいとき、開始タグはどちらにしますか?