ShellScript (Bash) よく使うループ文 まとめ

この記事では、私が実際よく使う
シェルスクリプトでのループ処理にフォーカスして、
まとめておこうと思います。

よく使うといっても、私自身
全部を覚えてるわけではないので、すぐにコピペしやすいように、
なるべく簡素に記載していきます。

あと、シェルスクリプトではありますが、
Bashじゃないとうまく動作しないものも含まれていますので、ご注意ください。

コマンド処理結果を元にループ for x in $(コマンド)

一番オーソドックスなループで、使用頻度も一番多い方法。

#!/bin/bash

# 何かしらの実行結果のリスト
list=$(ls)

# リストを一つずつ処理 
# list変数をダブルクォートで囲わないのがミソ
for f in $list; do
  echo "$f"
done

一旦、シェル変数に代入してますが、
もちろん、$(ls) として、直接for文に書くこともできます。

注意点としては、変数展開時にダブルクォートで囲わない事です。
囲ってしまうと、一つの要素とみなされて、ループが一回しかまわりません。

Zshで実行した場合は、ダブルクォートで囲っていなくても、
この現象がおこるので、思ったように動作しません。

展開された文字列は、
IFS変数によって区切られて、ループしています。
(スペース、タブ、改行)

連番のループ for n in $(seq A B)

シェルスクリプトの、一般的なfor文の書き方です。

#!/bin/bash

# seq で1〜10までループ
for i in $(seq 1 10); do
  echo "$i"
done

seqコマンドは、引数を3つにすると、
ステップ(増加数)を指定することもできます。
seq 1 2 10
2, 4, 6, 8, 10 と増加する。

また、seqコマンドに、-w オプションをつけると、
数字をゼロ埋めにして、桁数をあわせる事ができます。
seq -w 1 10
01, 02, 03, ...

Cスタイルのループ for ((i=0; i<10; i++))

Bashでは、C言語のfor文のように、
セミコロンで区切ったループを書くことができます。(Zshでも利用可能です)

#!/bin/bash

for ((i=0 ; i<10 ; i++)); do
  echo "$i"
done

インクリメントのところは、
i+=2 のように、好きな数で増加させる事もできます。

また、カンマで区切って、複数の変数を扱うことも可能です。

#!/bin/bash

for ((i=0, j=0; i<10; i++, j+=2)); do
    echo "$i $j"
done

テキストファイルを一行ずつループ while read

テキストファイルを読み込んで、一行ずつループする例です。
readコマンドで指定のシェル変数に、一行分の文字列が代入されます。

#!/bin/bash

# テキストファイルを読み込んで、一行毎にループ
while read line; do
  echo "$line"
done < sample.txt

プロセス置換

テキストファイルを用意したくない場合は、
コマンドの実行結果を、プロセス置換を使って渡す事ができます。

#!/bin/bash

# プロセス置換で、コマンドの実行結果を一行毎にループ
while read line; do
  echo "$line"
done < <(ls *)

サブシェルの罠

while read は、パイプでつなげて、出力結果を元にループする事もできます。
しかし、できるだけプロセス置換を利用するのを私はおすすめします。

#!/bin/bash

# パイプを使うと、ループ内はサブシェルで動いている。
cat sample.txt | while read line; do
  # ここはサブシェルなので、
  # 親のシェル変数は参照できるが、代入しても親シェルには反映されない。
  echo "$line"
done

パイプでつなげると、ループ内の処理は、サブシェルで動く事になります。
ループの外側(親シェル)にあるシェル変数をインクリメントしたりなどしたい場合、
思ったように動かないなどの罠があるので、理解しておきましょう。

無限ループ while true

下記のスクリプトは無限ループします。
もし実行した場合は、Ctrl + C で止めてください。

#!/bin/bash

while true; do
  echo "hoge"
  sleep 1
done

break と continue

for文も、while文も、
ループを抜けるときは、breakを使います。
処理の途中で、次のループにスキップしたい場合は、continue が使えます。

あとがき

基本的には、Bashで動かす前提で書きました。

shの実態はたいてい、bashになってることが多いのですが、
Ubuntuなんかは。ログインシェルはbashなのに、
shは、dashと呼ばれるシェルになっていたりします。

変なところでハマらないためにも、
できるだけ、bashスクリプトと明示するように。
シェバン(#!/bin/bash)も書いて、
実行権限の付与(chmod +x)をしておくのがよいでしょう。

読者のみなさんの参考になれば幸いです。


スペースを含む行をループしたい。 ShellScript (bash)

1件のコメント

コメントを残す