「シェルスクリプトの基礎 - 入出力」の版間の差分

272行目: 272行目:
  <span style="color:yellow">warn 'Warning message'</span>
  <span style="color:yellow">warn 'Warning message'</span>
  <span style="color:green">info 'Information message'</span>
  <span style="color:green">info 'Information message'</span>
<br><br>
== リダイレクションとパイプ ==
コマンドの実行結果は、通常、標準出力であるディスプレイに出力される。<br>
<br>
この実行結果はリダイレクション(>、>>)やパイプ(|)を使用することにより、<br>
ディスプレイではなくテキストファイルやコマンドに対して出力するように切り替えることができる。<br>
<br>
また、リダイレクションは、コマンドの出力先をテキストファイルに切り替える以外にも、<br>
コマンドへの入力元をテキストファイルに切り替えることもできる。<br>
<br>
なお、リダイレクションとパイプは、以下のように使い分ける。<br>
* リダイレクション
*: データを渡す対象がファイルである場合はリダイレクションを使用する。
*: <br>
* パイプ
*: データを渡す対象がコマンドである場合はパイプを使用する。
<br>
==== リダイレクション(>、»、<) ====
コマンドの実行結果の出力先をディスプレイからファイルへ切り替えたい場合は、リダイレクションを使用する。<br>
コマンドに続けてリダイレクション記号(>、>>)と出力先ファイルを指定することで、コマンドの実行結果をファイルへ書き込むことができる。<br>
<u>ファイルが存在しない場合は、新規にファイルが作成されて出力される。</u><br>
<br>
コマンドの出力をfile.txtへ上書きする。(既存の内容は全て消去される)<br>
command > file.txt
<br>
コマンドの出力をfile.txtへ追記する。(既存の内容の最下行に追加される)<br>
command >> file.txt
<br>
以下の3種類の応用例では、リダイレクションを使用してファイルの内容を全て削除している。<br>
> file
: >file
cat /dev/null >file
<br>
リダイレクションは、コマンドへの入力元をファイルに切り替えることもできる。<br>
# ファイルの内容をコマンドへ渡す
command < file.txt
<br>
コマンドに続けてリダイレクション記号(<)と入力元ファイルを指定することで、ファイルに対してコマンドを実行することができる。<br>
また、リダイレクション記号(<)は、コマンドへのリダイレクションではなく、ファイルディスクリプタ0番へのリダイレクションである。<br>
<br>
以下の例では、ファイルの行数を<code>wc</code>コマンドでカウントしている。<br>
file.txtファイルの内容
11111
22222
33333
<br>
# 実行
wc -l < file.txt
# 出力
5
<br>
以下の例では、リダイレクションでファイルを入力元として、ファイルの内容を出力している<br>
<syntaxhighlight lang="sh">
#!/bin/sh
# readコマンドで標準入力から1行ずつ読み込む
echo "while文にリダイレクション"
while read line
do
    echo "$line"
done < $1
# execコマンドを使用して、カレントシェルの標準入力へリダイレクトする
echo "カレントシェルにリダイレクション"
exec < $1
# readコマンドで標準入力から1行ずつ読み込む
while read line
do
    echo "$line"
done
exit 0
# 出力
while文にリダイレクション
11111
22222
33333
カレントシェルにリダイレクション
11111
22222
33333
</syntaxhighlight>
<br>
==== パイプ(|) ====
コマンドの実行結果を他のコマンドへ引き渡したい場合はパイプ(|)を使用する。<br>
複数コマンドをパイプで結合すると、コマンドは左から順に実行され、各コマンドの実行結果はパイプで結合された隣のコマンドへと引き渡される。<br>
実行結果を引き渡されたコマンドは、その引き渡された実行結果に対して処理を行う。<br>
<br>
なお、引き渡されるのは標準出力のみで、標準エラー出力は引き渡されない。<br>
command1 | command2
command1 | command2 | … | commandN
<br>
# ls コマンドの実行結果を wc コマンドに引き渡して行数をカウントする
ls | wc -l
# 標準エラー出力も渡す場合、パイプの前に2番を1番にリダイレクトする
ls hogehoge 2 > &1 | wc -l
<br>
==== ヒアドキュメント(<<) ====
コマンドの標準入力に対して、複数行にわたる任意の文字列を与えるには、ヒアドキュメントを使用する。<br>
ヒアドキュメントを使用すると、終了文字が出現するまでの文字列を、コマンドへの標準入力として与えることができる。<br>
<br>
ヒアドキュメント中では<code>``</code>や<code>$()</code>によるコマンド置換や、変数も使用可能である。<br>
ヒアドキュメント内でのコマンド置換や変数を完全に無効にする場合は、終了文字を'終了文字'というようにシングルクォートで囲むか、<br>
もしくは、\終了文字というようにバックスラッシュでエスケープする。<br>
command << 終了文字
<br>
以下の例のように、終了文字は行中にあっても無視される。<br>
ヒアドキュメントを終了するには、終了文字を1行でかつ余計な文字を付けずに記述する必要がある。<br>
余談であるが、以下の例で終了文字として使用されている_EOT_は、End Of Textの略である。前後の_は終了位置を強調するために付加している。<br>
# >記号の部分がヒアドキュメントとしてキーボードから入力した部分である
# その下部は、catコマンドがヒアドキュメントからの入力を出力した部分である
cat <<_EOT_
> hoge hoge
> fuga fuga
> foo foo _EOT_
> _EOT_ bar bar
> _EOT_
hoge hoge
fuga fuga
foo foo _EOT_
_EOT_ bar bar
# ヒアドキュメント中ではコマンド置換や変数も使用可能である
cat <<_EOT_
`echo "hoge"`
$(echo "fuga")
> $PATH
> $HOME
> _EOT_
hoge
fuga
/usr/local/bin:/bin:/usr/bin:/home/username/bin
/home/username
<br>
以下の例は、ヒアドキュメントを使用したシェルスクリプトである。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
# catの出力結果を標準エラー出力へ
if [ $# -ne 1 ]; then
    cat << _EOT_ 1 > &2
    引数を指定してください。
    Usage: $0 param
    _EOT_
    exit 1
fi
# $を表示する場合、\$のようにエスケープする
cat << _EOT_
    ヒアドキュメント中では変数も使用できます。
    \$1 は $1 です。
    _EOT_
# 終了文字をエスケープする場合、ヒアドキュメント中の変数は展開されない
cat << '_EOT_'
    シングルクオートで終了文字を囲むと変数は無視されます。
    \$1 は $1 です。
    `echo "コマンド置換も無視されます。"`
    _EOT_
cat << \_EOT_
    バックスラッシュでも同様です。
    \$1 は $1 です。
    `echo "コマンド置換も無視されます。"`
    _EOT_
# <<-とすると、ヒアドキュメント中の先頭にあるタブは無視される(スペースは無視されない)
cat <<-_EOT_
    終了文字の前に-を指定する場合、ヒアドキュメント中の先頭のタブは無視されます。
    ←タブ
    ←タブ
    _EOT_
exit 0
# 出力
ヒアドキュメント中では変数も使用できます。
$1 は HEREDOC です。
シングルクオートで終了文字を囲むと変数は無視されます。
\$1 は $1 です。
`echo "コマンド置換も無視されます。"`
バックスラッシュでも同様です。
\$1 は $1 です。
`echo "コマンド置換も無視されます。"`
終了文字の前に-を指定する場合、ヒアドキュメント中の先頭のタブは無視されます。
←タブ
←タブ
</syntaxhighlight>
<br>
複数行の文字列を出力する場合、このヒアドキュメントを使用することを推奨する。<br>
echoやprintfで複数行出力する場合は'や"で囲む必要があるため、出力する文字列にそれら自体が含まれているとエスケープする必要があるが、<br>
ヒアドキュメントであれば、それらのエスケープを意識する必要はない。<br>
<br>
以下に、ヒアドキュメントの使用方法をまとめる。<br>
* <code><< _EOT_</code>
*: 通常のヒアドキュメント。
*: ヒアドキュメント内で変数が使用可能。($を表示するには、\$のようにエスケープする)
*: コマンド置換が使用可能。
*: <br>
* <code><< '_EOT_'</code> または <code><< \_EOT_</code>
*: 変数展開およびコマンド置換を実行しないヒアドキュメント。
*: ヒアドキュメント内で変数は使用できない。($がそのまま出力される)
*: コマンド置換が使用不可。(``および$()がそのまま出力される)
*: <br>
* <code><< -_EOT_</code>
*: 行の先頭にあるタブを無視する通常のヒアドキュメント。
*: ヒアドキュメント内で変数を使用可能。($を表示するには、\$のようにエスケープする)
*: コマンド置換が使用可能。
*: ヒアドキュメント内の行の先頭にあるタブが無視される。
*: <br>
* <code><< -'_EOT_'</code> または <code><< -\_EOT_</code>
*: 行の先頭にあるタブを無視して、変数展開およびコマンド置換を実行しないヒアドキュメント。
*: ヒアドキュメント内で変数は使用できない。($がそのまま出力される)
*: コマンド置換が使用不可。(``および$()がそのまま出力される)
*: ヒアドキュメント内の行の先頭にあるタブが無視される。
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:シェルスクリプト]]
[[カテゴリ:シェルスクリプト]]