シェルスクリプトはあまり触らないから忘れちゃうのでメモっとく。
主にパイプとかリダイレクトとかプロセス置換とか。
パイプ
コマンドの出力を別のコマンドの入力にする
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> file
や2>&1 1> file
ではダメ
出力を闇に葬り去る
command &> /dev/null
ヒアドキュメント
コマンドに複数行の入力を渡す
command <<EOS
line1
line2
EOS
タブでインデントした複数行の入力を渡す
<<-
を使うと行頭のタブを取り除いた文字列が渡される。
command <<-EOS
line1
line2
EOS
line1
line2
複数行の入力をファイルに出力する
cat
コマンドに複数行の入力を渡し、リダイレクトでファイルへ出力する。
cat <<EOS > sample.txt
line1
line2
EOS
$ cat sample.txt
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}')