「シェルスクリプトの基礎 - 繰り返し文」の版間の差分
細 (Wiki がページ「繰り返し文(シェルスクリプト)」を「シェルスクリプトの基礎 - 繰り返し文」に、リダイレクトを残さずに移動しました) |
(→無限ループ) |
||
| 201行目: | 201行目: | ||
条件にNULLコマンドである:(コロン)を指定すると、無限ループになる。<br> | 条件にNULLコマンドである:(コロン)を指定すると、無限ループになる。<br> | ||
NULLコマンド:は、何もせずに終了コード0(真)を返すので、条件が常に真となるため、無限ループになる。<br> | NULLコマンド:は、何もせずに終了コード0(真)を返すので、条件が常に真となるため、無限ループになる。<br> | ||
<br> | |||
無限ループを終了させるには、Ctrlキー + Cキーで強制的に終了させるか、<br> | 無限ループを終了させるには、Ctrlキー + Cキーで強制的に終了させるか、<br> | ||
処理部分でif文またはcase文などの条件分岐で、<code>break</code>、<code>return</code>、<code>exit</code>コマンドを実行する。<br> | |||
<source lang="sh"> | <source lang="sh"> | ||
while : | while : | ||
| 210行目: | 211行目: | ||
</source> | </source> | ||
<br> | <br> | ||
以下の例では、無限ループにcase文(条件分岐)を組み込んでいる。<br> | |||
<br> | <br> | ||
<code>Repeat? (y/n) :</code>を表示した後、[y]キーを入力すると"Repeat!"と表示して処理が繰り返され、<br> | |||
[n]キーを入力すると、<code>Repeat end.</code>と表示して処理を終了させる。<br> | |||
<br> | <br> | ||
[y]キーまたは[n]キー以外のキーを入力すると、<code>Push y or n key.</code>と表示する。<br> | |||
その後、[y]キーまたは[n]キーのいずれかを入力するように促すメッセージを表示して、処理を繰り返す。<br> | |||
<source lang="sh"> | <source lang="sh"> | ||
#!/bin/bash | #!/bin/bash | ||
| 239行目: | 240行目: | ||
Repat? (y/n) :n ← nキーを入力 | Repat? (y/n) :n ← nキーを入力 | ||
Repeat end. | Repeat end. | ||
<br><br> | |||
== continueコマンド == | |||
continueコマンドを実行することにより、以降の処理をスキップして、ループの先頭に移動することができる。<br> | |||
また、breakコマンドと同様に、引数を指定することにより、ネストされたループ処理を一気にスキップすることも可能である。<br> | |||
<source lang="sh"> | |||
while 条件式 | |||
do | |||
… | |||
continue | |||
… | |||
done | |||
</source> | |||
<br> | |||
以下の例では、continueコマンドに引数を渡して、ネストされたループを一気にスキップしている。<br> | |||
<source lang="sh"> | |||
#!/bin/bash | |||
# 最初のexitコマンド回避用フラグ | |||
SKIP="ON" | |||
while : | |||
do | |||
if [ "$SKIP" != "ON" ]; then | |||
echo "continue 2 が実行されました." | |||
exit 0 | |||
fi | |||
# 以降のループでは上の処理をスキップしない | |||
SKIP="" | |||
while : | |||
do | |||
if [ "$CNT" = "ON" ]; then | |||
echo "continue が実行されました." | |||
continue 2 | |||
fi | |||
# continue フラグを立てる | |||
CNT="ON" | |||
continue | |||
# continue フラグをオフにする | |||
CNT="" | |||
done | |||
done | |||
</source> | |||
<br> | |||
上記の例の実行結果は、以下の通りである。<br> | |||
<br> | |||
最初のメッセージは、変数CNTにフラグを立てた後、continueコマンドを実行するために出力している。<br> | |||
次に、continue 2が実行されて、処理が1つ上のwhile文の先頭に移動する。<br> | |||
変数SKIPは、2段目の繰り返し処理に入る直前でオフにするので、continue 2コマンドを実行した後、メッセージを出力して終了する。<br> | |||
continue が実行されました. | |||
continue 2 が実行されました. | |||
<br><br> | |||
== 多重ループの制御 == | |||
<code>break</code>コマンドおよび<code>continue</code>コマンドは、数値を指定することにより、ネストされた多重ループを越えた移動ができる。<br> | |||
つまり、指定した数値の分だけ、上の階層のループを対象に実行される。<br> | |||
引数を省略した場合は、1を指定した場合と同じ動作になる。<br> | |||
break <数値> | |||
continue <数値> | |||
<br> | |||
以下の例では、<code>break</code>コマンドに2を指定して実行することにより、2重ループを一気に抜けている。<br> | |||
同様に、2重ループの先頭(1つ目のwhile文の先頭)に戻る場合は、<code>continue</code>コマンドの引数に2を指定して実行する。<br> | |||
<source lang="sh"> | |||
while : # 1つ目のループ | |||
do | |||
... | |||
while : # 2つ目のループ | |||
do | |||
... | |||
# 1つ目のwhile文の先頭に戻る | |||
continue 2 | |||
... | |||
# 1つ目のwhile文から抜ける | |||
break 2 | |||
... | |||
done | |||
done | |||
</source> | |||
<br><br> | <br><br> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:シェルスクリプト]] | [[カテゴリ:シェルスクリプト]] | ||
2020年10月30日 (金) 09:48時点における版
概要
繰り返し文は、変数にリストで指定した値を順番に代入し、その度にdoからdoneまでの処理を実行し、
リストの値を全てを代入し処理が完了したら繰り返しは終了となる。
for文
変数iに1から5までの数字を指定して、変数に代入された値をechoで表示させるというサンプルコードを以下に記述する。
#!/bin/bash
for i in 1 2 3 4 5
do
echo $i
done
# 出力 1 2 3 4 5
for文におけるリストの指定
リストの指定方法を以下に記載する。
コマンドの実行結果の使用
リスト部分には、コマンドの実行結果を値として使用でき、その場合は、コマンドをバッククォート(`)で囲む必要がある。
#!/bin/bash
for file in `ls /var/log/messages*`
do
echo $file
done
# 出力 /var/log/messages /var/log/messages-20170618 /var/log/messages-20170626 /var/log/messages-20170702 /var/log/messages-20170710
また、bashの場合は、$()も使用できる。
#!/bin/bash
for file in $(ls /var/log/messages*)
do
echo $file
done
seqコマンドの使用
seqコマンドは、指定した開始の数値から終わりの数値までを表示するというコマンドで、繰り返す回数を指定することができる。
例えば、1から5までをリストとして指定する場合は、seq 1 5と指定する。
また、開始が1からの場合は、開始の数値を省略することもできる。
seq 1 5 または seq 5 または seq 1 1 5
seqコマンドを使用して、1から5までを範囲指定して、ファイルを作成するというスクリプトを記述する。
file_1からfile_5までのファイルが作成される。
#!/bin/bash
for data in `seq 5`
do
touch file_$data
done
また、wオプションを使用して、ゼロパディングすることもできる。
# 01から10までを出力する seq -w 1 10
ブレーズ展開
bashの場合、ブレーズ展開機能を使用してリストを指定することもできる。
ブレーズ展開は、{開始..最後}といった形式で指定することで、簡単に範囲を指定することができる。
例えば、{1..5}で1から5を指定する場合、以下のように記述する。
#!/bin/bash
for i in {1..5}
do
echo $i
done
算術式の使用
bashの場合、以下のように、1から5までを指定することもできる。
#!/bin/bash
for ((i=1; i<6; i++))
do
echo $i
done
ファイルの読み込み
事前にリストに読み込ませるファイルを作成しておき、catコマンド等でファイルの中身を読み込むという方法ある。
list.txtファイルを事前に作成して、catコマンドでファイルの中身を読み込む。
#!/bin/bash
for i in `cat list.txt`
do
echo $i
done
コマンドライン引数の使用
リスト部分に"@$"を使用すると、シェルスクリプトを実行する際の引数を、リストの値にすることができる。
#!/bin/bash
for i in "$@"
do
echo $i
done
配列変数の使用
配列を使用してリストを指定することもできる。
配列arrayに1から5を設定して、それをリスト部分で呼び出す。
#!/bin/bash
array=(1 2 3 4 5)
for i in ${array[@]}
do
echo $i
done
while文
以下のサンプルコードでは、変数iが6より小さい間だけ、変数iに代入された値をechoで表示した後、
exprコマンドを使用して変数iに1を加算する。
#!/bin/bash
i=1
while [ $i -lt 6 ]
do
echo "$i"
i=`expr $i + 1`
done
# 出力 1 2 3 4 5
bashのみだが、exprコマンドは遅いので(())を使用した算術式の方が処理が速い。
#!/bin/bash
i=1
while ((i < 6))
do
echo $i
i=$(( i + 1 ))
done
while文における条件の指定
条件の指定にはtestコマンド(または[]コマンド)を使用する場合が多いが、それ以外も条件として指定することができる。
ファイルから読み込む
readコマンドを使用してlist.txtファイルの内容を読み込み、1行ずつ表示させる。
以下のシェルスクリプトを実行すると、list.txtファイルの内容を1行ずつ読み込み、その内容が表示される。
# list.txtファイルの内容 abc def ghi
#!/bin/bash
while read line
do
echo "$line"
done < ./list.txt
# 出力 abc def ghi
無限ループ
条件にNULLコマンドである:(コロン)を指定すると、無限ループになる。
NULLコマンド:は、何もせずに終了コード0(真)を返すので、条件が常に真となるため、無限ループになる。
無限ループを終了させるには、Ctrlキー + Cキーで強制的に終了させるか、
処理部分でif文またはcase文などの条件分岐で、break、return、exitコマンドを実行する。
while :
do
# 処理
done
以下の例では、無限ループにcase文(条件分岐)を組み込んでいる。
Repeat? (y/n) :を表示した後、[y]キーを入力すると"Repeat!"と表示して処理が繰り返され、
[n]キーを入力すると、Repeat end.と表示して処理を終了させる。
[y]キーまたは[n]キー以外のキーを入力すると、Push y or n key.と表示する。
その後、[y]キーまたは[n]キーのいずれかを入力するように促すメッセージを表示して、処理を繰り返す。
#!/bin/bash
while :
do
read -p "Repat? (y/n) :" key
case "$key" in
y) echo "Repeat!";;
n) echo "Repeat end."
break ;;
*) echo "Push y or n key.";;
esac
done
# 出力 Repeat? (y/n) :q ← yキーまたはnキー以外を入力 Push y or n key. Repat? (y/n) :y ← yキーを入力 Repeat! Repat? (y/n) :n ← nキーを入力 Repeat end.
continueコマンド
continueコマンドを実行することにより、以降の処理をスキップして、ループの先頭に移動することができる。
また、breakコマンドと同様に、引数を指定することにより、ネストされたループ処理を一気にスキップすることも可能である。
while 条件式
do
…
continue
…
done
以下の例では、continueコマンドに引数を渡して、ネストされたループを一気にスキップしている。
#!/bin/bash
# 最初のexitコマンド回避用フラグ
SKIP="ON"
while :
do
if [ "$SKIP" != "ON" ]; then
echo "continue 2 が実行されました."
exit 0
fi
# 以降のループでは上の処理をスキップしない
SKIP=""
while :
do
if [ "$CNT" = "ON" ]; then
echo "continue が実行されました."
continue 2
fi
# continue フラグを立てる
CNT="ON"
continue
# continue フラグをオフにする
CNT=""
done
done
上記の例の実行結果は、以下の通りである。
最初のメッセージは、変数CNTにフラグを立てた後、continueコマンドを実行するために出力している。
次に、continue 2が実行されて、処理が1つ上のwhile文の先頭に移動する。
変数SKIPは、2段目の繰り返し処理に入る直前でオフにするので、continue 2コマンドを実行した後、メッセージを出力して終了する。
continue が実行されました. continue 2 が実行されました.
多重ループの制御
breakコマンドおよびcontinueコマンドは、数値を指定することにより、ネストされた多重ループを越えた移動ができる。
つまり、指定した数値の分だけ、上の階層のループを対象に実行される。
引数を省略した場合は、1を指定した場合と同じ動作になる。
break <数値> continue <数値>
以下の例では、breakコマンドに2を指定して実行することにより、2重ループを一気に抜けている。
同様に、2重ループの先頭(1つ目のwhile文の先頭)に戻る場合は、continueコマンドの引数に2を指定して実行する。
while : # 1つ目のループ
do
...
while : # 2つ目のループ
do
...
# 1つ目のwhile文の先頭に戻る
continue 2
...
# 1つ目のwhile文から抜ける
break 2
...
done
done