Linux shellプログラミング構造化コマンドforループwhileループuntilループbreakコマンドcontinueコマンド詳細


目次
構造化コマンドforループwhileループuntilループbreakコマンドcontinueコマンドの使用
①forサイクル
forループ基本フォーマット:
値が複雑なリストの内容を読み込む
変数からリストを読み込みます.
コマンドから値を読み込みます.
フィールド区切り文字を変更するには、次の手順に従います.
ワイルドカードでディレクトリを読み込む
forループ実戦——ファイルデータのループ処理
②whileサイクル
whileサイクルの基本フォーマット
③untilサイクル
untillループの基本フォーマット:
         ループネスト
 
前言
>>サイクルを学習する目的:特定の条件に至るまで、いくつかのプロセスとコマンドを繰り返す方法を理解します.
>>>ループに関連するコマンドには、for、while、untilが含まれます.
 
 
①forサイクル
>>>bash shellはforコマンドを提供し、一連の値を巡るループを作成できます.
>>>forループの便利なリストは、各値がスペースで分割されていると仮定します.たとえば(1「2」「ベイ」)
>>>値の両方に二重引用符が使用されている場合、shellは二重引用符を値の一部としません.
 
forループ基本フォーマット:
for val in list
do
commands
done
またはfor val in list;do commands;done(常用)
 
forループ基本フォーマットの説明について:
>>>listパラメータは、反復に使用する一連の値を提供します.スペースで区切られた文字列でも、値を生成するコマンドでも構いません.
>>>forループが終了すると、変数valの値は最後に与えられた値を保持します(変数は残りのshellスクリプトで有効です).
          unset変数のみ変数が空になります
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in 0 7 5
do
    echo $val
done
echo "The last val:val=$val"
unset val
echo "After unset val:val=$val"
[bei@localhost test]$ bash for.sh
0
7
5
The last val:val=5
After unset val:val=

       完了forループ ,valは最後に与えられた値「5」を保持し、残りのshellスクリプトで有効になります.
       変数valを無効にする必要がある場合はunsetを使用します.
>>>doとdoneの間に、ネストif文を含む1つ以上のshellコマンドを入力できます.
[bei@localhost test]$ cat for.sh
#!/bin/bash
count=1
for i in 59 60 99
do
    if [ $i -ge 60 ]                            # for      if  
    then
        echo "Grade $count : $i"
    fi
    count=$[$count+1]
done
[bei@localhost test]$ bash for.sh
Grade 2 : 60
Grade 3 : 99

 
値が複雑なリストの内容を読み込む
質問:リスト内の値を巡回します.スペースまたは特殊文字があります.
メソッド:>>使用処理
           >>>二重引用符または一重引用符で処理
ケース
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in It's a lucky dog !
do
    echo $val
done
[bei@localhost test]$ bash for.sh
for.sh: line 2: unexpected EOF while looking for matching `''
for.sh: line 6: syntax error: unexpected end of file

>>>リストに特殊文字が存在し、エラーが発生します.
>>解決方法1:使用処理
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in It\'s a lucky dog \!
do
    echo $val
done
[bei@localhost test]$ bash for.sh
It's
a
lucky
dog
!

>>解決策2:二重引用符または一重引用符で処理(特殊文字だけでなくスペースのある値も出力できます)
>>>>shellは最外層の引用符を値の一部とせず、中の引用符が出力されます
[bei@localhost test]$ cat for.sh
#!/bin/bash
for val in "It's" a "lucky dog" "!"
do
    echo $val
done
[bei@localhost test]$ bash for.sh
It's
a
lucky dog                                        #            
!

 
変数からリストを読み込みます.
>>>リストが長い場合、直接forループの中にリストを置いて、美しくなくて、修正が面倒です
>>リストを変数に割り当ててから、変数の値を巡回できます.
ケース:
[bei@localhost test]$ cat for.sh
#!/bin/bash
list="1 2 3 4 5"     #       ,         ,           
list=$list" 6 7"     #       
for i in $list
do
    echo $i
done
[bei@localhost test]$ bash for.sh
1
2
3
4
5
6
7

 
コマンドから値を読み込みます.
使用方法
>>>file="xxx.txt"
>>>for I in `cat $file`                      #コマンドから値をフェッチします.
ケース
[bei@localhost test]$ cat txt
Guangdong Guangzhou
Guangdong Shenzhen
Guangdong Shantou
[bei@localhost test]$ cat for.sh
#!/bin/bash
list="./txt"               
for i in `cat $list`
do
    echo $i
done
[bei@localhost test]$ bash for.sh
Guangdong
Guangzhou
Guangdong
Shenzhen
Guangdong
Shantou

 
フィールド区切り文字を変更するには、次の手順に従います.
>>前の例では、コマンドから値を読み込むと、txtファイルの内容、行にスペースがあり、行の内容がそれぞれ出力され、同じ行に出力されません.
この問題は、セパレータを変更することで解決できます.
区切り文字とは
>>>セパレータは内部フィールドセパレータと呼ばれます(internal field separator)
>>>環境変数IFSによりbash shellフィールド区切り記号の一連の文字を定義
     set |grep IFS
     IFS=$'\t'  
>>デフォルトでbash shellのフィールド区切り文字:
     スペース()
     タブ(t)
     改行()
>>セパレータの変更方法:shellスクリプトでIFS環境変数を一時的に変更できます.
[bei@localhost test]$ cat txt
Guangdong Guangzhou
Guangdong Shenzhen
Guangdong Shantou
[bei@localhost test]$ cat for.sh
#!/bin/bash
IFS_old=$IFS
IFS=$'
' file='txt' for i in `cat $file` do     echo "$i" done IFS=$IFS_old [bei@localhost test]$ bash for.sh Guangdong Guangzhou Guangdong Shenzhen Guangdong Shantou

>>>スクリプトでIFS変数を一時的に変更する必要がある場合は、IFSのデフォルト値を保存し、一時IFS変数の使用が完了した後、IFSをデフォルト値に復元する必要があります.
>>複数の区切り文字を指定します.
     IFS=$'\t:;"'          #スペース、タブ、改行、セミコロン、二重引用符を区切り記号として使用
 
ワイルドカードでディレクトリを読み込む
ワイルドカード/var/historyを使用してこのディレクトリを巡り、ディレクトリの下のファイルが通常のファイルかどうかを判断します.
[bei@localhost test]$ cat for.sh
#!/bin/bash
for i in /var/history/*
do
if [ -f "$i" ]
then
echo "$i is exist and is a file"
else
echo "$i is exist and is not a file"
fi
done
[bei@localhost test]$ bash for.sh
/var/history/bei-507.log is exist and is a file
/var/history/root-0.log is exist and is a file

 
forループ実戦——ファイルデータのループ処理
結合されたテクノロジー:
>>ネストされたループの使用
>>IFS環境変数の変更
ケース:/etc/passwdファイルのデータを処理し、/etc/passwdファイルを行ごとに遍歴し、IFS変数の値をコロンに変更する必要がある
[bei@localhost test]$ cat loop.sh 
#!/bin/bash
IFS_OLD=$IFS
IFS=$'
' for line in `cat /etc/passwd` do echo "Vales in $line" IFS=: for value in $line do echo "$value" done done IFS=$IFS_OLD [bei@localhost test]$ bash loop.sh Vales in root:x:0:0:root:/root:/bin/bash root x 0 0 root /root /bin/bash Vales in bin:x:1:1:bin:/bin:/sbin/nologin bin x 1 1 bin /bin /sbin/nologin Vales in daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon x 2 2 daemon /sbin /sbin/nologin ......

 
 
 
②whileサイクル
>>whileコマンドはif-then文とforループの混在体であることは簡単に理解できます.
>>>whileコマンドでは、テストするコマンドを定義できます.定義したコマンドは、返される終了ステータスコードが0の場合、コマンドのセットをループします.
>>>テスト条件の終了ステータスコードが0である限り、whileコマンドの後ろのコードは、テスト条件のtestコマンドが返す終了ステータスコードが0でないまで実行され、whileコマンドは実行コマンドを終了します.
 
whileサイクルの基本フォーマット
while test command   #テストコマンド終了ステータスコードが0であると、コマンドother commandsが実行されます
do
other commands
done
説明:
>>>whileコマンドの鍵は、指定したtest commandが返す終了ステータスコードがループの実行に伴って変化することです.
>>>test commandの終了ステータスコードに変化がない場合
常に0の場合、デッドサイクルが発生し、other commandsが実行されます.
非0のままではother commandsは実行されません
>>>doneの後に[>>file]を追加すると、ループの結果出力がファイルにリダイレクトされます.
例:
[bei@localhost test]$ cat ./txt
[bei@localhost test]$ cat while.sh
#!/bin/bash
val=1
while [ $val -le 3 ]
do
        echo "$val"
        val=$[ $val + 1 ]
done >> ./txt
[bei@localhost test]$ bash while.sh
[bei@localhost test]$ cat ./txt
1
2
3

 
複数の試験条件がある場合は、最後の試験条件の終了ステータスコードに準じる
while test command1 
test command2
test command3 
…….
done
説明
>>このwhileサイクルはtest command 3の終了ステータスコードに準じる
>>>test command 1とtest command 2はループのジャンプに影響しません
 
 
③untilサイクル
>>>>untilコマンドとwhileコマンドの動作は、まったく逆です
>>>>untileコマンドでは、テストするコマンドを定義できます.定義したコマンドは、返される終了ステータスコードが0以外の場合、コマンドのセットをループします.
>>>テスト条件の終了ステータスコードが0でない限り、untilコマンドの後ろのコードは、テスト条件のtestコマンドが返す終了ステータスコードが0になるまで実行され、untilコマンドは実行コマンドを終了します.
>>一般的な理解:untilのテスト条件が成立するまで、untilサイクルは停止しません.
 
untillループの基本フォーマット:
until test command                        #テストコマンド終了ステータスコード非0は、コマンドother commandsを実行します.
do
other commands
done
 
例を挙げる
[bei@localhost test]$ cat until.sh
#!/bin/bash
val=8
until [ $val -gt 10 ]
do
    echo "$val" 
    val=$[ $val + 1 ]
done
[bei@localhost test]$ bash until.sh
8
9
10

説明:
val=8の場合、testコマンドは終了ステータスコードが0でないことを返し、untilループはdoの後のコマンドを実行する
val=9の場合、testコマンドは終了ステータスコードが0以外であることを返し、untilループはdoの後のコマンドを実行する
val=10の場合、testコマンドは終了ステータスコードが非0であることを返し、untilループはdoの後のコマンドを実行する
val=11の場合、testコマンドは終了ステータスコード0を返し、untilループは後のコマンドを実行せず、ループ停止
 
 
ループネスト
ネストされたループとは
>>ループ文は、ループ内で任意のタイプのコマンドを使用できます.ループ内で他のループコマンドが使用されている場合、ネストループと呼ばれます.
>>>ネストされた階層が多ければ多いほど、時間の複雑さは大きくなり、一般的に時間の複雑さは積関係です.
ケース:
[bei@localhost test]$ cat nested.sh
#!/bin/bash
for (( a=1;a<4;a++ ))
do
    echo "outside loop : $a"
    for (( b=1;b<4;b++ ))
    do
        echo "inside loop : $b"
    done
done
[bei@localhost test]$ bash nested.sh
outside loop : 1
inside loop : 1
inside loop : 2
inside loop : 3
outside loop : 2
inside loop : 1
inside loop : 2
inside loop : 3
outside loop : 3
inside loop : 1
inside loop : 2
inside loop : 3

ケース:
[bei@localhost test]$ cat nested.sh
#!/bin/bash
a=1
while [ $a -le 3 ]
do
        b=1
        echo "ouside loop : $a"
        until [ $b -ge 3 ]
        do
                echo "  inside loop : $b"
                b=$[$b+1]
        done
        a=$[$a+1]
done
[bei@localhost test]$ bash nested.sh
ouside loop : 1
        inside loop : 1
        inside loop : 2
ouside loop : 2
        inside loop : 1
        inside loop : 2
ouside loop : 3
        inside loop : 1
        inside loop : 2

 
 
④制御サイクル
>>>ループを制御する必要があるのはなぜですか?
ループが開始されると、ループを制御しない場合は、ループの反復が完了してからループが終了するまで待たなければなりません.
>>>ループの制御方法
2つのコマンドは、breakコマンドとcontinueコマンドのループ内部の状況を制御します.
 
breakコマンド
>>>進行中のループを終了(forループ、whileループ、untilループを含む)
ケース
[bei@localhost test]$ cat break.sh
#!/bin/bash
for i in 1 2 3 4 5
do
    if [ $i -le 3 ]
    then
        echo "$i"
    else
        echo "breaking"
        break
    fi
done
[bei@localhost test]$ bash break.sh
1
2
3
breaking

説明:forループでif-then条件を満たす場合、breakコマンドは実行されません.          条件を満たさない場合はbreakコマンドを実行し、処理中のループ、すなわちforループからジャンプする
 
>>>ネストされたループに対しては、breakに最も近いループから飛び出すだけで、外のループから飛び出すことはありません
ケース
[bei@localhost test]$ cat break.sh
#!/bin/bash
for((a=1;a<4;a++))
do
        echo "a=$a"
        for((b=1;b<4;b++))
        do
                if [ $b -lt 3 ]
                then
                        echo "  b=$b"
                else
                        echo "breaking"
                        break
                fi
        done
done
[bei@localhost test]$ bash break.sh
a=1
  b=1
  b=2
breaking
a=2
  b=1
  b=2
breaking
a=3
  b=1
  b=2
breaking

説明:breakコマンドは、外部のループに影響を与えることなく、最も近いループから飛び出します.
 
>>>ネストされたループの場合、外部ループを停止する必要がある場合は、パラメータ値break nを使用してnレイヤループをスキップできます.
ここで、nは、ループをスキップするレベルを表し、デフォルトではnの値は1、すなわち、現在のループをスキップするレベルである
ケース
[bei@localhost test]$ cat break.sh
#!/bin/bash
for((a=1;a<4;a++))
do
        echo "a=$a"
        for((b=1;b<4;b++))
        do
                if [ $b -lt 3 ]
                then
                        echo "  b=$b"
                else
                        echo "breaking"
                        break 2
                fi
        done
done
[bei@localhost test]$ bash break.sh
a=1
  b=1
  b=2
breaking

説明:breakコマンドの2は、2つのループから飛び出していることを意味します.つまり、外のループも停止しています.
 
continueコマンド
>>>このループの後のコードの一部しかスキップされませんが、ループ全体を完全に終了するわけではありません.
ケース
[bei@localhost test]$ cat continue.sh
#!/bin/bash
for((a=1;a<=2;a++))
do
        echo "a=$a"
        for((b=1;b<=3;b++))
        do
                if [ $b -ne 2 ]
                then
                        echo "  b=$b"
                else
                        continue
                        echo "command1"
                fi
                echo "command2"
        done
done
[bei@localhost test]$ bash continue.sh
a=1
  b=1
command2
  b=3
command2
a=2
  b=1
command2
  b=3
command2

説明:b=1の場合、正常出力
  b=2の場合、continueコマンドを実行し、command 1およびcommand 2を含むこのループの後のコマンドの一部をスキップする                   forサイクルは止まらない
  b=3の場合、ループが停止しないため、通常出力
 
 
 
説明:
>>以上は私の勉強のまとめです
>>>また間違いがあれば、伝言を残して、指摘してください
>>>自分の考えを共有し、学び合うこともできます