鍍金池/ 教程/ Linux/ shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)四十一天----列出文件 ls 和 od 命令
shell 學(xué)習(xí)小結(jié)
shell 學(xué)習(xí)第二十八天----case 語句
shell 學(xué)習(xí)四十四天----尋找文件
shell 學(xué)習(xí)三十五天----波浪號(hào)展開與通配符
shell 學(xué)習(xí)三十八天----執(zhí)行順序和 eval
shell 學(xué)習(xí)四十八天----文件校驗(yàn)和匹配
shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)第十一天----sed 正則的精確控制
shell 學(xué)習(xí)第十七天----awk 命令
shell 學(xué)習(xí)三十九天----內(nèi)建命令
shell 學(xué)習(xí)四十五天----xargs
shell 學(xué)習(xí)三十七天----引用
shell 學(xué)習(xí)第十六天----join 練習(xí)
shell 學(xué)習(xí)第二十四天----提取開頭或結(jié)尾數(shù)行
shell 學(xué)習(xí)第九天----分組
shell 學(xué)習(xí)第五天----基本的 I/O 重定向
shell 學(xué)習(xí)第十五天----使用 cut 選定字段
shell 學(xué)習(xí)四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學(xué)習(xí)第八天----擴(kuò)展正則表達(dá)式 (ERE)
shell 學(xué)習(xí)第十九天----文本塊排序
shell 學(xué)習(xí)第二十一天----重新格式化段落
shell 學(xué)習(xí)三十六天----命令替換
shell 學(xué)習(xí)第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學(xué)習(xí)四十二天----使用 touch 更新文件時(shí)間
shell 學(xué)習(xí)五十一天----top 命令查看進(jìn)程列表
shell 學(xué)習(xí)第一天
shell 學(xué)習(xí)五十四天----進(jìn)程系統(tǒng)調(diào)用的追蹤 strace
shell 學(xué)習(xí)五十天----查看進(jìn)程 ps 命令
shell 學(xué)習(xí)第二十七天----退出狀態(tài)和 if 語句
shell 學(xué)習(xí)第二十三天----打印
shell 學(xué)習(xí)三十三天----關(guān)于重定向
shell 學(xué)習(xí)四十九天----進(jìn)程建立
shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)五十五天----進(jìn)程記賬
shell 學(xué)習(xí)總結(jié)一
shell 學(xué)習(xí)第二十六天----變量與算數(shù)
shell 學(xué)習(xí)第二十二天----計(jì)算行數(shù), 字?jǐn)?shù)以及字符數(shù)
shell 學(xué)習(xí)五十八天----/proc 文件系統(tǒng)
shell 學(xué)習(xí)第二十五天----神器的管道符
shell 學(xué)習(xí)第三十二天----read 讀取一行
sheel 學(xué)習(xí)第三天
shell 學(xué)習(xí)----小結(jié)
shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)第三十一天----函數(shù)問題
shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十三天----臨時(shí)性文件的建立與使用
shell 學(xué)習(xí)四十七天----文件比較 cmp,diff,patch
shell 學(xué)習(xí)三十四天----printf 詳解
shell 學(xué)習(xí)五十七天 ----linux 任務(wù)管理,針對(duì)上一講的總結(jié)和擴(kuò)展
shell 學(xué)習(xí)第六天----小結(jié)
shell 學(xué)習(xí)第十三天----sed 案例分析
shell 學(xué)習(xí)第七天----基礎(chǔ)正則表達(dá)式 (BRE)
shell 學(xué)習(xí)第十二天----行與字符串
shell 學(xué)習(xí)小結(jié)四
shell 學(xué)習(xí)第二十九天----循環(huán)
shell 學(xué)習(xí)五十二天----刪除進(jìn)程 kill 命令
shell 學(xué)習(xí)五十六天----延遲進(jìn)程調(diào)度
shell 學(xué)習(xí)第四天----華麗的 printf 輸出
shell 學(xué)習(xí)第十五天----join 連接字段
shell 學(xué)習(xí)完結(jié)篇----希望你能看到
shell 學(xué)習(xí)第二天
shell 學(xué)習(xí)五十三天----捕獲信號(hào) trap

shell 學(xué)習(xí)第三十天----break,continue,shift,getopts

break 和 continue

這兩個(gè)命令分別用來退出循環(huán),或跳到循環(huán)體的其他地方。使用 while 與 break,等待用戶登錄。

bash 代碼:

printf “Enter username:”
read user
while true
do
if who | grep “$user” >/dev/null
then 
break;
fi
sleep 30
done

等待特定用戶,每 30 秒確認(rèn)一次

true 命令什么事也不必做,只是成功的退出。這用于編寫無限循環(huán),即會(huì)永久的執(zhí)行循環(huán)。在編寫無限循環(huán)時(shí),必須放置一個(gè)退出條件在循環(huán)體內(nèi),正如這里所作的。另有一個(gè) false 命令和它有點(diǎn)相似,只是很少的用到,也不做人和事,僅表示不成功的狀態(tài).false 命令常見于無線的 until false..循環(huán)中。

continue 命令則用于提早的開始下一段重復(fù)動(dòng)作,也就是在到大循環(huán)體的底部之前。

break 與 continue 命令都可以接受可選的數(shù)值參數(shù),可分別用來之處要中斷 (break) 或繼續(xù)多少個(gè)被包含的循環(huán) (如果循環(huán)技術(shù)需要的是一個(gè)在運(yùn)行時(shí)可被計(jì)算的表達(dá)式時(shí),可以使用 $((...)) )。

案例

while condition1 // 外循環(huán)
do...
while condition2 // 內(nèi)循環(huán)
do..
break; 外循環(huán)的終端
done
done

break 與 continue 特別具備終端或繼續(xù)多個(gè)循環(huán)層的能力。從而以簡(jiǎn)潔的形式彌補(bǔ)了 shell 語言里缺乏 goto 關(guān)鍵字的不足。

使用 continue 的案例

\#!/bin/bash
limit=19
echo "printing Number 1 throught 20"
a=0
while [$a -le"$limit"]
do
        let a++
        #let a+=1
        #a=$(($a+1))
        if ["$a" -eq 3] || ["$a" -eq 11]
        then
                continue
        fi
        echo -n "$a"
done

輸出結(jié)果:

printing Number 1 throught 20 

1 2 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20  

由此可見 continue 的作用是結(jié)束本次循環(huán),執(zhí)行下一次循環(huán)

使用 break 的案例

\#!/bin/bash
limit=19
echo "printing Number 1 throught 20"
a=0
while [$a -le"$limit"]
do
        let a++
        #let a+=1
        #a=$(($a+1))
        if ["$a" -eq 3] || ["$a" -eq 11]
        then
                break
        fi
        echo -n "$a"
done

輸出結(jié)果:

printing Number 1 throught 20

1 2

由此可見,break 的作用是退出當(dāng)前循環(huán)。

shift

我們知道,對(duì)于位置變量或命令行參數(shù),其個(gè)數(shù)必須是確定的,或者當(dāng) Shell 程序不知道其個(gè)數(shù)時(shí),可以把所有參數(shù)一起賦值給變量 $*。若用戶要求 Shell 在不知道位置變量個(gè)數(shù)的情況下,還能逐個(gè)的把參數(shù)一一處理,也就是在 $1 后為 $2,在 $2 后面為 $3 等。在 shift 命令執(zhí)行前變量 $1 的值在 shift 命令執(zhí)行后就不可用了。

案例

\#!/bin/bash
until [$# -eq 0]
do
        echo " 第一個(gè)參數(shù)為:$1 參數(shù)個(gè)數(shù)為:$#"
        shift
done

執(zhí)行命令:./shift.sh 1 2 3 4

輸出為:

第一個(gè)參數(shù)為:1 參數(shù)個(gè)數(shù)為:4
第一個(gè)參數(shù)為:2 參數(shù)個(gè)數(shù)為:3
第一個(gè)參數(shù)為:3 參數(shù)個(gè)數(shù)為:2
第一個(gè)參數(shù)為:4 參數(shù)個(gè)數(shù)為:1

分析:

  • 從上可知 shift 命令每執(zhí)行一次,變量的個(gè)數(shù) ($#) 減一,而變量值提前一位。
  • shift 可以用來向左移動(dòng)位置參數(shù)。
  • Shell 的名字 $0

第一個(gè)參數(shù) $1
第二個(gè)參數(shù) $2
第 n 個(gè)參數(shù) $n
所有參數(shù) $@ 或 $*
參數(shù)個(gè)數(shù) $#

案例

bash 代碼:

until [-z"$1"]  # Until all parameters used up
do
  echo "$@"
  shift
done

命令:./shift1.sh 1 2 3 4 5 6 7 8 9 10

輸出:

1 2 3 4 5 6 7 8 9 10   
2 3 4 5 6 7 8 9 10   
3 4 5 6 7 8 9 10   
4 5 6 7 8 9 10   
5 6 7 8 9 10   
6 7 8 9 10   
7 8 9 10   
8 9 10   
9 10   
10  

getopts 命令

語法:

getopts option_spec variable [arguments...]

現(xiàn)在來看一個(gè)簡(jiǎn)單的例子:

\#!/bin/bash
echo $*
while getopts ":a:bc:" opt
do
        case $opt in
                a)
                echo $OPTARG
                echo $OPTIND
                ;;
                b)
                echo "b $OPTIND"
                ;;
                c)
                echo "c $OPTIND"
                ;;
                ?)
                echo "error"
                exit 1
        esac
done
echo $OPTIND
shift $(($OPTIND-1))
echo $0
echo $*

如果執(zhí)行命令:./getopts.sh -a 11 -b -c 6

結(jié)果為:

-a 11 -b -c 6  
11  
3  
b 4  
c 6  
6  
./getopts.sh  

看分析:

getopts 后面的字符串就是可以使用的選項(xiàng)列表,每個(gè)字母代表一個(gè)選項(xiàng),后面帶:的意味著選項(xiàng)除了定義本身之外,還會(huì)帶上一個(gè)參數(shù)作為選項(xiàng)的值,比如 a:在實(shí)際的使用中就會(huì)對(duì)應(yīng) -a 11,選項(xiàng)的值就是 11;getopts 字符串中沒有跟隨:的是開關(guān)型選項(xiàng),不需要再指定值,相當(dāng)于 true/false,只要帶了這個(gè)參數(shù)就是 true。如果命令行中包含了沒有在 getopts 列表中的選項(xiàng),會(huì)有警告信息,如果在整個(gè) getopts 字符串前面也加上個(gè):,就能消除警告信息了。使用 getopts 識(shí)別出各個(gè)選項(xiàng)之后,就可以配合 case 來進(jìn)行相應(yīng)的操作了。optarg 這個(gè)變變,getopts 修改了這個(gè)變量。這里變量 $optarg 存儲(chǔ)相應(yīng)選項(xiàng)的參數(shù),而 $optind 總是存儲(chǔ)原始 $* 中下一個(gè)要處理的元素 (不是參數(shù),而是選項(xiàng),此處值得的是 a,b,c 這三個(gè)選線,而不是那些數(shù)字,當(dāng)然數(shù)字也是會(huì)占有位置的) 位置。

while getopts ":a:bc:" opt # 第一個(gè)冒號(hào)表示忽略錯(cuò)誤;字符后面的冒號(hào)表示該選項(xiàng)必須有自己的參數(shù)。

使用 getopts 處理參數(shù)雖然是方便,但仍然有兩個(gè)小小的局限:

  1. 選項(xiàng)參數(shù)的格式必須是 -d val,而不能是中間沒有空格的 -dval。
  2. 所有選項(xiàng)參數(shù)必須寫在其它參數(shù)的前面,因?yàn)?getopts 是從命令行前面開始處理,遇到非 - 開頭的參數(shù),或者選項(xiàng)參數(shù)結(jié)束標(biāo)記 -- 就中止了,如果中間遇到非選項(xiàng)的命令行參數(shù),后面的選項(xiàng)參數(shù)就都取不到了。
  3. 不支持長(zhǎng)選項(xiàng),也就是 --debug 之類的選項(xiàng)

案例

\#!/bin/bash
while getopts "ab:cd:" opt
do
        case $opt in
                a)
                echo $OPTIND
                ;;
                b)
                echo $OPTIND
                echo $OPTARG
                ;;
                c)
                echo $OPTIND
                ;;
                d)
                echo $OPTIND
                echo $OPTARG
        esac
done
shift $(($OPTIND-1))

使用命令:./getopts1.sh -a -b foo -c -d haha

得到結(jié)果:

2  
4  
foo  
5  
7  
haha  

最后使用 shift $(($OPTIND-1)) 的作用是:通過 shift $(($OPTIND - 1)) 的處理,$* 中就只保留了除去選項(xiàng)內(nèi)容的參數(shù),可以在其后進(jìn)行正常的 shell 編程處理了。 貌似不用也可以。

如果出現(xiàn)這種情況:

  • getopts “:ab:c” 第一個(gè)冒號(hào)代表的含義是:第一個(gè)冒號(hào)表示忽略錯(cuò)誤,即當(dāng)出現(xiàn)沒有的選項(xiàng)是會(huì)忽略;字符后面的冒號(hào)表示該選項(xiàng)必須有自己的參數(shù)。