シェルの入出力制御あれこれ

  • 180
    いいね
  • 4
    コメント

シェルスクリプトはあまり触らないから忘れちゃうのでメモっとく。
主にパイプとかリダイレクトとかプロセス置換とか。

パイプ

コマンドの出力を別のコマンドの入力にする

command1 | command2 | command3

先頭n行を表示する

command | head -10

末尾n行を表示する

command | tail -10

コマンドの出力を標準出力とファイルに出力する

command | tee file

リダイレクト

ファイルの内容をコマンドの標準入力へ渡す

command < file

コマンドの出力をファイルへ出力する

command > file

コマンドの出力をファイルに追加する

command >> file

標準エラー出力をファイルに出力する

command 2> file

2>の間にスペースを入れてはいけない。

標準エラー出力を標準出力に出力する

command 2>&1

標準出力と標準エラー出力を別々のファイルに出力する

command 1> file1 2> file2

標準出力と標準エラー出力を同じファイルに出力する

command > file 2>&1
command &> file

1> file 2> file2>&1 1> fileではダメ

出力を闇に葬り去る

command &> /dev/null

ヒアドキュメント

コマンドに複数行の入力を渡す

command <<EOS
line1
line2
EOS

タブでインデントした複数行の入力を渡す

<<-を使うと行頭のタブを取り除いた文字列が渡される。

command <<-EOS
    line1
    line2
EOS
出力
line1
line2

シェル変数

コマンドの結果を変数へ格納する

コマンドをバッククォートで囲む。
bashならばコマンドを$( )で囲む記法も使える。入れ子もOK。

VAR1=`command`
VAR2=$(command $(command2))

ファイルの内容を変数へ格納する

ファイル名を$(cat )で囲む。
bashならばファイル名を$(< )で囲む記法も使える。

VAR1=$(cat file)
VAR2=$(<file)

※詳細は man bash で Command Substitution (コマンド置換) の解説を読むこと。

変数の値をファイルとしてコマンドへ渡す

ヒアストリング<<<を使用する。

command <<< $VAR1

複数コマンドの出力をまとめて制御する

{}で囲むと複数のコマンドの出力をまとめて制御できる。

#!/bin/bash
{
  command1
  command2  
} 1> file1 2> file2

execでも同じことができる。

#!/bin/bash
exec 1> file1
exec 2> file2
command1
command2

シェルスクリプトが '> $logfile 2>&1' だらけにならなくて済んだ話 - 続・ラフなラボ

プロセス置換

<(list)>(list)をプロセス置換という。これを使うとコマンドの結果をファイルとして扱ったりできる。

bashのプロセス置換機能を活用して、シェル作業やスクリプト書きを効率化する - 双六工場日誌
Bash のプロセス置換が便利な件 - 理系学生日記

command1とcommand2の結果をcommand3にファイルとして渡す

command3 <(command1) <(command2)

上は以下のように書いたのと同じ動作。

command1 > file1
command2 > file2
command3 file1 file2

command1の結果をcommand2とcommand3に渡す

command1 | tee >(command2) | command3

command1の標準出力をcommand2に、標準エラー出力をcommand3に渡す

command1 1> >(command2) 2> >(command3)

ログ出力の実践例

標準出力、標準エラー出力をファイルにも出力する

command 1> >(tee file1) 2> >(tee file2 >&2) 

file1に全ログ、file2にフィルタリングしたログを出力する

command 2>&1 | tee file1 | grep -i error > file2

file1に全ログ、file2と標準出力にフィルタリングしたログを出力する

command 2>&1 | tee file1 | grep -i error | tee file2

file1と標準出力に全ログ、file2にフィルタリングしたログを出力する

command 2>&1 | tee >(grep -i error > file2) | tee file1

標準エラー出力の行頭に[ERROR]を付けて標準出力に出力する

command 2> >(awk '{print "[ERROR]", $0}')