Loose-Info.com
Last Update 2022/06/28
TOP - 各種テスト - bash - シェル文法

シェル文法


テスト項目

(01) 単純コマンド

(02) パイプライン

(03) リスト(list)

(04) (  リスト  )

(05)  リスト  ; }

(06) ((  式  ))

(07) [[   式   ]]

(08) for

(09) select

(10) case

(11) if  リスト1  ; then  リスト2  ; ... fi

(12) while

(13) until

(14) シェル関数


(1) 単純コマンド


c_sample1.c(実行ファイル c_sample1)
#include <stdio.h> int main(int argc, char *argv[]) { int i; for (i=0; i<argc; i++) { printf("引数 %d -- %s\n", i, argv[i]); } return 100; }

実行結果(1)
$ ./c_sample1 arg1 arg2 引数 0 -- ./c_sample1 <--- 0番目の引数は最初の単語となる実行コマンド 引数 1 -- arg1 <--- 以降、引数として空白で区切られた単語 引数 2 -- arg2 <--- $

実行結果(2)
リダイレクトを含む場合
$ ./c_sample1 arg1 arg2 > c_sample1.txt $ cat c_sample1.txt 引数 0 -- ./c_sample1 引数 1 -- arg1 引数 2 -- arg2 $

実行結果(3)
終了ステータスに関するテスト
$ ./c_sample1 arg1 arg2 引数 0 -- ./c_sample1 引数 1 -- arg1 引数 2 -- arg2 $ echo $? 100 <--- サンプルコマンドの終了ステータス(コードで指定された戻り値) $ sleep 10 <--- sleepコマンドの実行 $ echo $? 0 <--- sleepコマンド正常終了時の終了ステータス $ sleep 10 ^C <--- 実行中のsleepコマンドをCtrl-cで中断 $ echo $? 130 <--- シグナル(SIGINT (数値で2))で終了のため 2 + 128 = 130

(2) パイプライン


c_sample2_1.c(実行ファイル c_sample2_1)
#include <stdio.h> int main() { /* 標準出力へ出力 */ printf("c_sample2\n"); /* 標準エラーへ出力 */ fprintf(stderr, "stderr c_sample2\n"); return 0; }

c_sample2_2.c(実行ファイル c_sample2_2)
#include <stdio.h> int main() { char s[100]; /* 標準入力から読み込み */ while (fgets(s, 100, stdin) != NULL) { /* 読み込んだ文字列を標準出力へ出力 */ printf("stdin : %s", s); } printf("\n"); return 0; }

実行結果(1)
制御演算子「|」でc_sample2_1の標準出力からc_sample2_2の標準入力に接続
$ ./c_sample2_1 | ./c_sample2_2 stderr c_sample2 <--- 標準エラーは標準入力へ接続されない stdin : c_sample2 $

実行結果(2)
制御演算子「|&」でc_sample2_1の標準出力からc_sample2_2の標準入力に接続
$ ./c_sample2_1 |& ./c_sample2_2 stdin : stderr c_sample2 <--- 標準エラーも標準入力へ接続される stdin : c_sample2 $

実行結果(3)
「time」による経過時間情報の出力
$ time ./c_sample2_1 <--- 1つのコマンドに「time」を付けて実行 c_sample2 stderr c_sample2 real 0m0.001s <--- コマンドの経過時間情報を出力 user 0m0.000s sys 0m0.001s $ time ./c_sample2_1 | ./c_sample2_2 <--- パイプラインに「time」を付けて実行 stderr c_sample2 stdin : c_sample2 real 0m0.002s <--- パイプライン全体の経過時間情報を出力 user 0m0.001s sys 0m0.001s $ time ./c_sample2_1 | ./c_sample2_2 ; ./c_sample2_1 <--- パイプラインに「;」でコマンドを追加 stderr c_sample2 stdin : c_sample2 real 0m0.002s user 0m0.000s sys 0m0.001s c_sample2 <--- パイプラインの経過時間情報を出力後にコマンドを実行 stderr c_sample2

(3) リスト(list)


c_sample3_1.c(実行ファイル c_sample3_1)
#include <stdio.h> int main() { /* 標準出力へ出力 */ printf("c_sample3_1\n"); return 0; }

c_sample3_2.c(実行ファイル c_sample3_2)
#include <stdio.h> int main() { char s[100]; /* 標準入力から読み込み */ fgets(s, 100, stdin); /* 読み込んだ文字列を標準出力へ出力 */ printf("stdin : %s", s); return 0; }

c_sample3_3.c(実行ファイル c_sample3_3)
#include <stdio.h> int main() { /* 終了ステータス 1 */ return 1; }

sample3.sh
#!/bin/bash # 以下の部分全体がリスト(list) # パイプラインとコマンドの区切りに「;」を使用 # パイプライン ; コマンド ; コマンド ./c_sample3_1 | ./c_sample3_2 ; echo "start" ; echo "end" echo # 改行もコマンド区切りとして機能 # 下記コマンド実行で最終終了ステータスに1をセット ./c_sample3_3 echo "現在の最終終了ステータス : $?" # コマンドが制御演算子「&」で終わっている場合はバックグラウンドで実行 echo "バックグラウンドでコマンドを実行" sleep 1 & # バックグラウンドでコマンド実行の際は、コマンド終了を待たずに終了ステータス0が戻される echo "バックグラウンドで実行直後の最終終了ステータス : $?" # 現在稼働中のプロセスを表示 ps echo echo "ANDリスト" # 「&&」で区切られたリスト # 左側のパイプライン(コマンド)の終了ステータスが「0」の場合に右側を実行 ./c_sample3_1 | ./c_sample3_2 && echo "ANDリスト終了" echo echo "ORリスト" # 「||」で区切られたリスト # 左側のパイプライン(コマンド)の終了ステータスが「0」以外の場合に右側を実行 ./c_sample3_3 || echo "ORリスト終了" echo echo "sleep 1 実行" sleep 1 echo # 再度現在稼働中のプロセスを表示 ps

実行結果
$ ./sample3.sh stdin : c_sample3_1 <--- パイプラインを含む「;」区切りのリストを実行 start end 現在の最終終了ステータス : 1 バックグラウンドでコマンドを実行 バックグラウンドで実行直後の最終終了ステータス : 0 <--- バックグラウンドでコマンド実行直後の終了ステータス PID TTY TIME CMD 255 pts/0 00:00:00 bash 295 pts/0 00:00:00 sample3.sh 299 pts/0 00:00:00 sleep <--- バックグラウンドで実行中 300 pts/0 00:00:00 ps ANDリスト stdin : c_sample3_1 ANDリスト終了 <--- ANDリストを終端まで実行 ORリスト ORリスト終了 <--- ORリストを終端まで実行 sleep 1 実行 <--- sleepコマンド実行後稼働中プロセスの確認 PID TTY TIME CMD 255 pts/0 00:00:00 bash 295 pts/0 00:00:00 sample3.sh 305 pts/0 00:00:00 ps $

(4) (  リスト  )


sample4.sh
#!/bin/bash n=1 echo "n = $n" echo # 「;」で区切られたリスト (echo "(リスト)[1]ここから" ; i=2 ; echo "n = $n" ; echo "i = $i" ; echo "(リスト)[1]ここまで") echo # 改行で区切られたリスト ( echo "(リスト)[2]ここから" echo "n = $n" n=3 echo "n = $n" echo "(リスト)[2]ここまで" ) echo echo "n = $n" echo "i = $i"

実行結果
$ ./sample4.sh n = 1 <--- サブシェル外で変数に値を代入 (リスト)[1]ここから n = 1 <--- サブシェル外で代入された変数値は有効 i = 2 (リスト)[1]ここまで (リスト)[2]ここから n = 1 n = 3 (リスト)[2]ここまで n = 1 <--- サブシェル内で代入された変数値はサブシェル外では無効 i = <--- 〃 $

(5)  リスト  ; }


sample5.sh
#!/bin/bash n=1 echo "n = $n" echo # 「;」で区切られたリスト # 「{」とリスト間の空白文字とリストと「}」間の「;」など、単語分割のための適切なメタ文字は必須 { echo "(リスト)[1]ここから" ; i=2 ; echo "n = $n" ; echo "i = $i" ; echo "(リスト)[1]ここまで" ; } echo # 改行で区切られたリスト { echo "(リスト)[2]ここから" echo "n = $n" n=3 echo "n = $n" echo "(リスト)[2]ここまで" } echo echo "n = $n" echo "i = $i"

実行結果
$ ./sample5.sh n = 1 <--- 「{ }」外で変数に値を代入 (リスト)[1]ここから n = 1 <--- 「{ }」外で代入された変数値は有効 i = 2 (リスト)[1]ここまで (リスト)[2]ここから n = 1 n = 3 (リスト)[2]ここまで n = 3 <--- 「{ }」内で代入された変数値も有効 i = 2 <--- 〃 $

(6) ((  式  ))


sample6.sh
#!/bin/bash # AND・ORリストによる (( 式 )) の動作テスト # cmd1 && cmd2 : cmd1が0を返した場合にcmd2を実行 # cmd1 || cmd2 : cmd1が0以外を返した場合にcmd2を実行 # (( 式 )) : 「式の値」が0ではない場合、ステータス0を返す # $(( 式 )) : 「式」の算術式評価による式の値(算術式展開) # パラメータ展開・文字列展開・コマンド置換・クォートの削除を実行 echo "引数個数 : $#" echo echo "等価演算子による算術式評価" echo "算術式展開 \$((\$# == 2)) : $(($# == 2))" ; (($# == 2)) && echo "((\$# == 2)) : 0を返す" echo "算術式展開 \$((\$# != 2)) : $(($# != 2))" ; (($# != 2)) || echo "((\$# != 2)) : 1を返す" echo echo "代入演算子による算術式評価" echo "算術式展開 \$((n1 = 3)) : $((n1 = 3))" ; ((n1 = 3)) && echo "((n1 = 3)) : 0を返す" echo echo "インクリメント演算子による算術式評価" echo "算術式展開 \$((n2 = 3)) : $((n2 = 3))" echo "算術式展開 \$((n2++)) : $((n2++))" ((n2 = 3)) && ((n2++)) && echo "((n2 = 3)) : 0を返す --- ((n2++)) : 0を返す" echo "n2 = $n2" echo # 変数bbbに1を代入 bbb=1 echo "文字列と数値0による式の評価" echo "算術式展開 \$((\"aaa\" == 0)) : $(("aaa" == 0))" ; (("aaa" == 0)) && echo "((\"aaa\" == 0)) : 0を返す" echo "算術式展開 \$((\"bbb\" == 0)) : $(("bbb" == 0))" ; (("bbb" == 0)) || echo "((\"bbb\" == 0)) : 1を返す" echo "算術式展開 \$((\"bbb\" == 1)) : $(("bbb" == 1))" ; (("bbb" == 1)) && echo "((\"bbb\" == 1)) : 0を返す" echo

実行結果
$ ./sample6.sh a b 引数個数 : 2 等価演算子による算術式評価 算術式展開 $(($# == 2)) : 1 <--- 算術式展開による算術式の評価結果(式の値) (($# == 2)) : 0を返す <--- 「式の値」が0ではないためステータス0を返す 算術式展開 $(($# != 2)) : 0 (($# != 2)) : 1を返す <--- 「式の値」が0のためステータス1を返す 代入演算子による算術式評価 算術式展開 $((n1 = 3)) : 3 ((n1 = 3)) : 0を返す <--- 「式の値」が0ではないためステータス0を返す インクリメント演算子による算術式評価 算術式展開 $((n2 = 3)) : 3 算術式展開 $((n2++)) : 3 <--- パラメータ展開が評価前のため「式の値」は3 ((n2 = 3)) : 0を返す --- ((n2++)) : 0を返す <--- 2つの「式の値」が0ではないためステータス0を返す n2 = 4 <--- 変数の値は評価時の演算結果を反映 文字列と数値0による式の評価 (注)この項目の下記コメントは、出力結果などからの推測によるもの 算術式展開 $(("aaa" == 0)) : 1 <--- 変数名参照による展開とクォートの削除により「0 == 0」 (("aaa" == 0)) : 0を返す 算術式展開 $(("bbb" == 0)) : 0 <--- 変数名参照による展開とクォートの削除により「1 == 0」 (("bbb" == 0)) : 1を返す 算術式展開 $(("bbb" == 1)) : 1 <--- 変数名参照による展開とクォートの削除により「1 == 1」 (("bbb" == 1)) : 0を返す

(7) [[   式   ]]


sample7.sh
#!/bin/bash # AND・ORリストによる [[ 式 ]] の動作テスト # cmd1 && cmd2 : cmd1が0を返した場合にcmd2を実行 # cmd1 || cmd2 : cmd1が0以外を返した場合にcmd2を実行 # [[ 式 ]] : 式の評価値によって0または1を返す # チルダ展開・パラメータと変数の展開・算術式展開・コマンド置換・プロセス置換・クォート除去を実行 n=123 s="abc" echo "n = $n" echo "s = $s" echo echo "算術比較の実行" [[ $n -eq 123 ]] && echo "[[ \$n -eq 123 ]] : 0を返す" [[ $n -ne 123 ]] || echo "[[ \$n -ne 123 ]] : 1を返す" echo echo "文字列比較の実行" [[ $s == "abc" ]] && echo "[[ \$s == \"abc\" ]] : 0を返す" [[ $s != "abc" ]] || echo "[[ \$s != \"abc\" ]] : 1を返す" echo echo "ファイルの存在確認の実行" echo "\$0 = $0" [[ -f "$0" ]] && echo "[[ -f \"\$0\" ]] : 0を返す" [[ -f "$0.txt" ]] || echo "[[ -f \"\$0.txt\" ]] : 1を返す" echo str="123 abc" echo "パターンマッチング" [[ $0 == *.sh ]] && echo "[[ \$0 == *.sh ]] : 0を返す" [[ $0 == *[.,@]sh ]] && echo "[[ \$0 == *[.,@]sh ]] : 0を返す" [[ $str == 123[[:blank:]]abc ]] && echo "[[ \$str == 123[[:blank:]]abc ]] : 0を返す" [[ $str != 23[[:blank:]]abc ]] && echo "[[ \$str != 23[[:blank:]]abc ]] : 0を返す" echo echo "正規表現によるパターンマッチング" [[ $0 =~ ^.+\.sh$ ]] && echo "[[ \$0 =~ ^.+\.sh\$ ]] : 0を返す" [[ $0 =~ *[.,@]sh ]] || echo "[[ \$0 == *[.,@]sh ]] : 0以外を返す" [[ $str =~ "23 abc" ]] && echo "[[ \$str =~ \"23 abc\" ]] : 0を返す" [[ $str =~ 23[[:blank:]]abc ]] && echo "[[ \$str =~ 23[[:blank:]]abc ]] : 0を返す" echo ""式に関する演算子" [[ ! ( $n && $s && $s == "123" ) && ! $s == "abcd" ]] \ && echo "[[ ! ( \$n && \$s && \$s == \"123\" ) && ! \$s == \"abcd\" ]] : 0を返す" n=0 ; [[ $(( ++n )) && $(( ++n )) ]] \ && echo "[[ \$(( ++n )) && \$(( ++n )) ]] --- \$n = $n --- 0を返す" n=0 ; [[ $(( ++n )) || $(( ++n )) ]] \ && echo "[[ \$(( ++n )) || \$(( ++n )) ]] --- \$n = $n --- 0を返す" n=0 ; [[ ( $s == "123" ) && $(( ++n )) ]] \ || echo "[[ ( \$s == \"123\" ) && \$(( ++n )) ]] --- \$n = $n --- 1を返す" n=0 ; [[ ( $s == "123" ) || $(( ++n )) ]] \ && echo "[[ ( \$s == \"123\" ) || \$(( ++n )) ]] --- \$n = $n --- 0を返す"

実行結果
$ ./sample7.sh n = 123 s = abc 算術比較の実行 [[ $n -eq 123 ]] : 0を返す <--- -eq : 数値が等しければtrue。式がtrueなので結果として0を返す [[ $n -ne 123 ]] : 1を返す <--- -ne : 数値が等しくなければtrue。式がfalseなので結果として1を返す 文字列比較の実行 [[ $s == "abc" ]] : 0を返す <--- 文字列が等しければtrue。式がtrueなので結果として0を返す [[ $s != "abc" ]] : 1を返す <--- 文字列が等しくなければtrue。式がfalseなので結果として1を返す ファイルの存在確認の実行 $0 = ./sample7.sh [[ -f "$0" ]] : 0を返す <--- ファイルが存在するとtrue。式がtrueなので結果として0を返す パターンマッチング [[ $0 == *.sh ]] : 0を返す <--- 演算子「==」で文字列がパターン(右辺)にマッチすると0を返す [[ $0 == *[.,@]sh ]] : 0を返す <--- 「[...]」による任意文字指定も可能 [[ $str == 123[[:blank:]]abc ]] : 0を返す <--- 「[...]」の間で文字クラスの指定も可能 [[ $str != 23[[:blank:]]abc ]] : 0を返す <--- 演算子「!=」はマッチしない場合に0を返す 正規表現によるパターンマッチング [[ $0 =~ ^.+\.sh$ ]] : 0を返す <--- 演算子「=~」により正規表現によるパターンマッチが可能 [[ $0 == *[.,@]sh ]] : 0以外を返す <--- パターンマッチしない場合は1、正規表現が間違いの場合は2を返す [[ $str =~ "23 abc" ]] : 0を返す <--- 引用符を使用した文字列の指定も可能 [[ $str =~ 23[[:blank:]]abc ]] : 0を返す <--- 文字クラスの指定も可能 式に関する演算子 式に関する演算子 [[ ! ( $n && $s && $s == "123" ) && ! $s == "abcd" ]] : 0を返す <--- 演算子&& : 全体の結果はtrue [[ $(( ++n )) && $(( ++n )) ]] --- $n = 2 --- 0を返す <--- 演算子&& : 両方の++nが実行される [[ $(( ++n )) || $(( ++n )) ]] --- $n = 1 --- 0を返す <--- 演算子|| : 最初の++nが実行されtrueとなり次の++nは実行されない [[ ( $s == "123" ) && $(( ++n )) ]] --- $n = 0 --- 1を返す <--- 演算子&& : 最初の式の評価がfalseとなるため次の++nは実行されない。全体の結果もfalse [[ ( $s == "123" ) || $(( ++n )) ]] --- $n = 1 --- 0を返す <--- 演算子|| : 最初の式の評価がfalseとなるが次の++nは実行される。全体の結果はtrue ( 式 ) : 演算子の通常の優先度を変更。「式」の値を返す ! 式 : 「式」がfalseのときtrue 式1 && 式2 : 「式1」と「式2」の両方がtrueであればtrue 式1 || 式2 : 「式1」と「式2」のどちらかがtrueであればtrue 式1の値のみで条件式全体の戻り値が決定される場合、式2は評価されない

(8) for


sample8.sh
#!/bin/bash echo "for 変数名" for a do echo "$a" done echo files=( $(cat sample8.txt) ) n=0 echo "for 変数名 in ... ;" for a in ${files[@]} do n=$(( ++n )) echo "$n行目 $a" done echo echo "for (( 式1 ; 式2 ; 式3 ; )) ;" for (( i=0 ; i < ${#files[@]} ; ++i )) do echo "$(( i+1 ))行目 ${files[i]}" done

sample8.txt
line1 line2 line3

実行結果
$ ./sample8.sh arg1 arg2 for 変数名 arg1 <--- 「in ...」が無い場合は、設定された位置パラメータを順次変数にセット arg2 セットされた位置パラメータごとにdo~done間を実行 for 変数名 in ... ; 1行目 line1 <--- 「in ...」に続く単語を展開したリストを順次変数にセット 2行目 line2 リストの要素ごとにdo~done間を実行 3行目 line3 for (( 式1 ; 式2 ; 式3 ; )) ; 1行目 line1 <--- 式1評価後、式2の評価が0となるまで、do~done間の実行と式3評価を実行 2行目 line2 3行目 line3

(9) select


sample9.sh
#!/bin/bash # 入力プロンプトの設定 PS3="番号で選択してください : " echo "selectテスト(1)" echo "in ... 無し" echo "位置パラメータから選択肢を生成" select s do echo "REPLY = $REPLY" echo "s = \"$s\"" if [[ $s ]]; then # 正しい選択肢を選択した場合は終了 break fi done echo "選択された値 : $s" echo echo "selectテスト(2)" echo "in ... 有り" echo "in ... から選択肢を生成" n=0 select s in 加算 リセット 終了 do if [[ $s == "終了" ]]; then # 終了を選択した場合は終了 echo "終了" break elif [[ $s == "加算" ]]; then n=$(( ++n )) else n=0 fi echo "n = $n" done echo

sample9.txt
選択肢a 選択肢b 選択肢c

実行結果
$ ./sample9.sh $(cat sample9.txt) selectテスト(1) in ... 無し 位置パラメータから選択肢を生成 1) 選択肢a <--- 位置パラメータに設定されたsample9.txtの各行の文字列 2) 選択肢b 「1)」などの番号は自動的に付加される 3) 選択肢c 番号で選択してください : <--- PS3に設定されたプロンプト 1) 選択肢a <--- 空入力の場合は再度選択肢リストを出力 2) 選択肢b 3) 選択肢c 番号で選択してください : a REPLY = a <--- 読み込まれた入力値は変数REPLYに保存 s = "" <--- 対応する選択数値以外の入力は、指定変数に選択文字列が設定されない 番号で選択してください : 1 REPLY = 1 s = "選択肢a" <--- 対応する選択数値の入力は、指定変数に選択文字列が設定される 選択された値 : 選択肢a selectテスト(2) in ... 有り in ... から選択肢を生成 1) 加算 <--- in ... から単語分割され、番号が自動付加された文字列を出力 2) リセット 3) 終了 番号で選択してください : 1 n = 1 番号で選択してください : 1 n = 2 番号で選択してください : 2 n = 0 番号で選択してください : 1 n = 1 番号で選択してください : 1 n = 2 番号で選択してください : 3 終了

(10) case


sample10.sh
#!/bin/bash echo "マッチングパターン例(1)" case "$1" in a*) echo "1文字目a" ;; b*) echo "1文字目b" ;; c*) echo "1文字目c" ;; esac echo echo "マッチングパターン例(2)" echo "「|」区切りによる記述" case "$1" in a* | b* | c* | d* | e*) echo "1組" ;; f* | g* | h* | i* | j*) echo "2組" ;; k* | l* | m* | n* | o*) echo "3組" ;; *) echo "4組" ;; esac echo echo "リストの終端が「;;&」" case "$1" in a*) echo "1文字目a" ;;& ?a*) echo "2文字目a" ;;& ??a*) echo "3文字目a" ;;& ???a*) echo "4文字目a" ;; esac echo echo "リストの終端が「;&」" case "$1" in a*) echo "a出現後処理(1)" ;& ?a*) echo "a出現後処理(2)" ;& ??a*) echo "a出現後処理(3)" ;& ???a*) echo "a出現後処理(4)" ;; esac

実行結果
$ ./sample10.sh baca マッチングパターン例(1) 1文字目b <--- 1文字目の「b」がマッチ リストの終端が「;;」の場合、1度マッチすると以降のマッチングは実行されない マッチングパターン例(2) 「|」区切りによる記述 1組 <--- 1文字目の「b」が「|」区切りからなる1組目にマッチ リストの終端が「;;」の場合、1度マッチすると以降のマッチングは実行されない リストの終端が「;;&」 2文字目a <--- 次のパターンに対するマッチングが実行される 4文字目a <--- リストの終端が「;&」 a出現後処理(2) <--- マッチして対応した処理が実行された場合、次のパターンに対応した処理も実行される a出現後処理(3) <--- a出現後処理(4) <---

(11) if  リスト1  ; then  リスト2  ; ... fi


sample11.sh
#!/bin/bash [[ $# -gt 1 ]] && echo "[[ \$# -gt 1 ]] : 終了ステータス0" [[ $# -eq 1 ]] && echo "[[ \$# -eq 1 ]] : 終了ステータス0" echo if [[ $# -gt 1 ]]; then echo "引数リスト" for a do echo "$a" done elif [[ $# -eq 1 ]]; then echo "引数 : $1" else echo "引数無し" fi

実行結果
$ ./sample11.sh <--- 引数無し 引数無し $ ./sample11.sh arg1 <--- 1つの引数 [[ $# -eq 1 ]] : 終了ステータス0 引数 : arg1 $ ./sample11.sh arg1 arg2 <--- 2つの引数 [[ $# -gt 1 ]] : 終了ステータス0 引数リスト arg1 arg2

(12) while


sample12.sh
#!/bin/bash # 「$#」が0より大きければ実行 while [[ $# -gt 0 ]] do echo "$1" shift done

実行結果
$ ./sample12.sh arg1 arg2 <--- 2つの引数 arg1 arg2 $ ./sample12.sh arg1 arg2 arg3 <--- 3つの引数 arg1 arg2 arg3

(13) until


sample13.sh
#!/bin/bash # 「$#」が1より小さくなるまで実行 until [[ $# -lt 1 ]] do echo "$1" shift done

実行結果
$ ./sample12.sh arg1 arg2 <--- 2つの引数 arg1 arg2 $ ./sample12.sh arg1 arg2 arg3 <--- 3つの引数 arg1 arg2 arg3

(14) シェル関数


sample14.sh
#!/bin/bash # 関数名() samplefunc1() { echo "samplefunc1()" while [[ $# -gt 0 ]] do echo "$1" shift done echo } # function 関数名 function samplefunc2 { echo "function samplefunc2" until [[ $# -lt 1 ]] do echo "$1" shift done echo } # function 関数名 複合コマンド リダイレクト function samplefunc3 { echo "function samplefunc3 複合コマンド リダイレクト" until [[ $# -lt 1 ]] do echo "$1" shift done echo } > sample14.txt # 関数呼び出し samplefunc1 arg1 arg2 samplefunc2 arg1 arg2 arg3 samplefunc3 "$@" echo "関数外" for a do echo "$a" done

実行結果
$ ./sample14.sh arg1 arg2 arg3 arg4 <--- 4つの引数で実行 samplefunc1() arg1 <--- 関数内の新規位置パラメータ arg2 <--- function samplefunc2 arg1 <--- 関数内の新規位置パラメータ arg2 <--- arg3 <--- 関数外 arg1 <--- シェルスクリプト起動時の4つの引数 arg2 arg3 arg4 $ cat sample14.txt <--- リダイレクトにより出力 function samplefunc3 複合コマンド リダイレクト arg1 <--- 関数内の新規位置パラメータ($@を引数にして呼び出し) arg2 <--- arg3 <--- arg4 <---

実行環境

GNU bash, version 5.1.16
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1


コード例・出力内容中の表記

・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。