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

引数と終了コード — $1 と exit で外から制御する

この記事は、基礎コマンドからシェルスクリプトまでLinuxの実践的なスキルを1からマスターする「Linux入門講座の一部」です。
./a.sh foo barの値を $1 $2 $@ $# $0で受け取り、${2:--} で既定値を補い、$? の確認とexit 0 / exit 1で成否を返す実用スクリプトを、図解とブラウザ端末で書いて実行します。

引数を受け取る — $1 / $2 / $0

スクリプトは実行時に値を渡せます。

./a.sh foo barのように後ろに並べた値を引数といい、スクリプトの中では$1が1番目、$2が2番目の引数になります。

$0はスクリプト自身の名前、$#は渡された引数の個数、$@は全引数をまとめて表します。

これらを使うと、固定の値ではなく実行のたびに違う入力でスクリプトを動かせます

書き方意味
$1 $21番目・2番目の引数echo "$1 then $2"
$0スクリプト自身の名前echo "running $0"
$#渡された引数の個数echo "argc=$#"
$@すべての引数をまとめてecho "all: $@"
引数の対応
./a.sh foo bar$1 = foo$2 = bar$# = 2$@ = foo bar1 番目2 番目個数全体
渡した値が$1 $2に入り、$#で個数、$@で全体をまとめて扱えます。
set -- foo bar                   # 位置パラメータを擬似的に設定
echo "1st: $1"                   # foo
echo "2nd: $2"                   # bar
echo "argc: $#"                  # 2
echo "all: $@"                   # foo bar

ファイル名などの値を引数で受け取り、そのまま表示するスクリプトを作成します。

vi args.shargs.shを開き、iで挿入モードに入って、先頭行に#!/bin/shを書いてください。

② 1番目の引数($1)と2番目の引数($2)、引数の個数($#)、全引数($@)、スクリプト名($0)をそれぞれ表示する処理を書いてください。

Escを押し:wqで保存してから、実行権限を付けてください。

./args.sh foo barの形で引数を 2 つ渡して実行し、どの値がどの変数に入ったかを確認してください。書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。(正しく実行できれば解説が表示されます)

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

既定値を補う — ${1:-def}

引数が渡されないこともあります。

${1:-default}と書くと、$1が未指定または空のときにdefaultが使われ、指定があればその値が使われます。

これにより、引数があれば従い、無ければ安全な既定値で動くスクリプトが書けます。

$#を見れば、必要な数の引数が来ているかも判定できます。

書き方意味
${1:-def}$1が未指定ならdefを使うname=${1:-guest}
${2:-def}$2が未指定ならdefを使うsep=${2:--}
既定値の補い方
sep=${2:--}$2 = barsep = bar$2 は無いsep = -(既定値)渡せば省けば指定どおり既定値を使う
${2:--}は、2番目を渡せばその値、省けば既定値-を使います。
set --                           # 引数なしで実行した状態を再現
echo "${1:-guest}"               # 未指定なので guest
set -- alice                     # 1番目に値を渡した状態
echo "${1:-guest}"               # 値があるので alice

区切り文字を引数で受け取り、省略時は既定値を使うスクリプトを作成します。

vi format.shformat.shを開き、iで挿入モードに入って、先頭行に#!/bin/shを書いてください。

② 1番目の引数を対象名として受け取り、2番目の引数を区切り文字として受け取ってください。ただし2番目が未指定のときは既定値(たとえば-)を使うように${2:-...}で書き、対象名と区切り文字を表示してください。

Escを押し:wqで保存してから、実行権限を付けてください。

④ まず./format.sh fooのように2番目を省いて実行し、区切り文字が既定値になることを確認してください。書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

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

成否を返す — $? と exit N

コマンドは終わるときに終了コードという 0〜255 の数を返します。

0は成功、0以外は失敗を表す慣習です。

直前のコマンドの終了コードは$?で読み取れます。

grepで見つかれば0、見つからなければ1のように、結果に応じて値が変わります。

スクリプト側からはexit Nで終了コードを明示できます。

exit 0は成功、exit 1は失敗として返すのが一般的です。

呼び出し側はこの値を$?&& ||で受け取り、成功時だけ次の処理へ進む、といった制御に使えます。

exitを省くと最後に実行したコマンドの終了コードがそのまま返ります。

書き方意味
$?直前のコマンドの終了コードgrep x f; echo $?
exit N終了コードNでスクリプトを終えるexit 1
終了コードの流れ
処理が成功exit 0$? = 0処理が失敗exit 1$? = 1返す読む返す読む成功失敗
スクリプトは成功ならexit 0、失敗ならexit 1を返し、呼び出し側は$?で結果を読み取ります。
printf 'apple\nbanana\n' > fruits.txt   # 素材を作成
grep apple fruits.txt > /dev/null
echo "found? $?"                          # 見つかったので 0
grep mango fruits.txt > /dev/null
echo "found? $?"                          # 見つからないので 1

引数で受けた語をファイルから探し、結果に応じた終了コードを返すスクリプトを作成します。

vi search.shsearch.shを開き、iで挿入モードに入って、先頭行に#!/bin/shを書いてください。

② スクリプト内で素材ファイルを作成し、1番目の引数で受け取った語をそのファイルから検索してください。見つかれば成功メッセージを出してexit 0、見つからなければ失敗メッセージを出してexit 1を返す処理を書いてください。

Escを押し:wqで保存してから、実行権限を付けてください。

./search.sh foo barの形で実行し、続けてecho $?で終了コードを確認してください。書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

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

全引数を順に処理する — $@ と $#

引数の数が決まっていないとき、$1 $2を順に書く代わりに$@forで回すと、渡された分だけ繰り返し処理できます

for x in "$@"; do … doneの形で1つずつ取り出し、件数は$#で表示すると、いくつ渡されても同じスクリプトで扱えます。

複数ファイルをまとめて処理するツールでよく使う書き方です。

書き方意味
"$@"全引数を1語ずつ安全に渡す(for用・要ダブルクォート)for x in "$@"; do
$#渡された引数の個数echo "count=$#"
全引数のループ処理
./a.sh foo bar baz$# = 3$@ = foo bar bazfor x in "$@"- foo- bar- baz個数全体1 つずつ表示for で繰り返す
$#で個数を知り、$@forで1つずつ取り出して各引数を処理します。
set -- foo bar baz               # 位置パラメータを擬似的に設定
echo "argc: $#"                  # 3
for x in "$@"; do
  echo "- $x"                    # - foo / - bar / - baz
done

渡された全引数を1つずつ処理し、件数も表示するスクリプトを作成します。

vi list.shlist.shを開き、iで挿入モードに入って、先頭行に#!/bin/shを書いてください。

② 引数の個数を$#で表示し、続けて$@forで1つずつ取り出して各引数を行ごとに表示する処理を書いてください。

Escを押し:wqで保存してから、実行権限を付けてください。

./list.sh foo bar bazの形で引数を 3 つ渡して実行し、件数と各引数が順に表示されることを確認してください。書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

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

理解度チェック

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

Q1./a.sh foo barを実行したとき$2には何が入りますか?

Q2${1:-guest}の意味として正しいものはどれですか?

Q3直前のコマンドが成功したかを表す終了コードを読み取る書き方はどれですか?