一、簡(jiǎn)介
Shell中別名可以對(duì)命令進(jìn)行重新命名,方便用戶記憶長(zhǎng)命名和定制自己熟悉的工作環(huán)境;列表是一組命名以邏輯與、邏輯或的關(guān)系串在一起,實(shí)現(xiàn)腳本程序的邏輯控制;數(shù)組是一重點(diǎn),涉及數(shù)組的賦值、操作和字符串的處理,以及利用數(shù)組實(shí)現(xiàn)堆棧和二維數(shù)組等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
二、詳解
1、別名
對(duì)linux命令重新命名,主要考慮到很多l(xiāng)inux命令帶有冗長(zhǎng)的選項(xiàng)和參數(shù),頻繁使用這些長(zhǎng)命令極易造成用戶使用上的不便。別名的命令關(guān)鍵字是alias,基本格式為alias name='original-command'(等號(hào)兩邊不能有空格)。如alias ipconfig=ifconfig。若要?jiǎng)h除已經(jīng)設(shè)置的別名,使用內(nèi)建命令unalias,unalias -a表示刪除所有已設(shè)置的別名,unalias
alias-name表示僅刪除alias-name別名。
- #!/bin/bash
-
- shopt -s expand_aliases #打開expand_aliases選項(xiàng)
- alias detail="ls -l"
- detail /root/in* #別名支持通配符*
- echo
- directory=/root/
- prefix=in*
- alias vardetail="ls -l $directory$prefix" #雙引號(hào)和單引號(hào)在處理空格時(shí)是等價(jià)的,
- #但設(shè)置vardetail引用了變量,此處只能使用雙引號(hào)
- vardetail
-
- echo "Deleting all aliases:"
- unalias -a #刪除所有的別名
- detail
- vardetail
若要在腳本中使用別名功能,必須在腳本使用shopt -s expand_aliases命令打開expand_aliases(表示別名可以被擴(kuò)展)選項(xiàng),未打開,alias命令建立的別名不會(huì)執(zhí)行。
要注意的是:在諸如if/then結(jié)構(gòu)、循環(huán)和函數(shù)等混合型結(jié)構(gòu)中不能使用alias命令設(shè)置別名,但可以執(zhí)行在混合型結(jié)構(gòu)之外所設(shè)置的別名。
2、列表
(1)shell中列表是由一串命令用與運(yùn)算(&&)和或運(yùn)算(||)連接而成,分別稱為與列表和或列表。與列表的格式為:命令1 &&命令2&&
命令3 &&...
&&命令n,從左到右依次執(zhí)行命名,直到某命令返回FALSE時(shí)(退出狀態(tài)為非0)與列表執(zhí)行終止。或列表的格式為:命令1
|| 命令2 ||
命令3 ||...
||命令n,從左到右依次執(zhí)行命名,但是當(dāng)某命令返回TRUE時(shí)(退出狀態(tài)為0)或列表執(zhí)行終止。
(2)與列表控制輸入?yún)?shù)個(gè)數(shù)和返回狀態(tài)碼
- #!/bin/bash
-
- MAXARGS=3
- ERROR=68
- test $# -ne $MAXARGS && echo "Usage: `basename $0` $MAXARGS arguments" && exit $ERROR
- echo "Less than $MAXARGS arguments are passed to this script."
- exit 0
(3)或列表控制輸入?yún)?shù)個(gè)數(shù)和返回狀態(tài)碼
- #!/bin/bash
-
- MAXARGS=3
- ERROR=68
- test $# -eq $MAXARGS || (echo "Usage: `basename $0` $MAXARGS arguments" && false) || exit $ERROR
- echo "Correct arguments are passed to this script."
- exit 0
可以對(duì)比或列表和與列表的語句,由于echo命令總是返回TRUE,要將echo和false進(jìn)行與運(yùn)算從而返回FALSE值。其中test命令實(shí)際上是或列表的嵌套,在使用與或列表嵌套時(shí)需要利用圓括號(hào)區(qū)分邏輯運(yùn)算的優(yōu)先級(jí)。
3、數(shù)組
(1)賦值和取值
數(shù)組(Array)是一個(gè)由若干同類型變量組成的集合,數(shù)組均由連續(xù)的存儲(chǔ)單元組成,最低地址對(duì)應(yīng)于數(shù)組的第一個(gè)元素,最高地址對(duì)應(yīng)于最后一個(gè)元素。Shell只支持一維數(shù)組,array[x]表示array數(shù)組的第x+1個(gè)元素,支持的最大數(shù)值標(biāo)號(hào)是599
147 937 791。shell取得數(shù)組值(引用數(shù)組元素)格式是:${array[x]}。
- #!/bin/bash
-
- city[0]=Nanjing #對(duì)第1、2個(gè)數(shù)組元素賦值
- city[1]=Beijing
- city[9]=Melbourne #對(duì)第10個(gè)數(shù)組元素賦值
- city[15]=NewYork #對(duì)第16個(gè)數(shù)組元素賦值
-
- echo "city[0]=${city[0]}"
- echo "city[1]=${city[1]}"
- echo "city[9]=${city[9]}"
- echo "city[15]=${city[15]}"
- echo "city[2]=${city[2]}" #未初始化數(shù)組的值為空
- echo "city[10]=${city[10]}"
Shell中允許數(shù)組空缺元素,即可以不連續(xù)地給數(shù)組賦值。還可以用圓括號(hào)將一組值賦給數(shù)組。
- #!/bin/bash
-
- city=(Nanjing Beijing Melbourne NewYork) #圓括號(hào)內(nèi)以空格為分隔符,依次賦給數(shù)組元素
-
- echo "city[0]=${city[0]}"
- echo "city[1]=${city[1]}"
- echo "city[2]=${city[2]}"
- echo "city[3]=${city[3]}"
- echo "city[4]=${city[4]}" #未被初始化輸出空
- echo "city[5]=${city[5]}"
- #!/bin/bash
-
- city=(Nanjing [10]=Atlanta Massachusetts Marseilles) #指定所賦元素的標(biāo)號(hào),并以此標(biāo)號(hào)為起點(diǎn)繼續(xù)賦值
-
- echo "city[0]=${city[0]}" #city[0]=Nanjing
- echo "city[1]=${city[1]}" #city[1]=
- echo "city[10]=${city[10]}" #city[10]=Atlanta
- echo "city[11]=${city[11]}" #city[11]=Massachusetts
- echo "city[12]=${city[12]}" #city[12]=Marseilles
- echo "city[13]=${city[13]}" #city[13]=
既然圓括號(hào)內(nèi)允許對(duì)數(shù)組指定元素進(jìn)行賦值,那么完全可以按照任意順序指定任意元素對(duì)數(shù)組賦值。例如:
- city=([2]=Nanjing [10]=Atlanta [1]=Massachusetts [5]=Marseilles)
(2)位置參數(shù)中$@和$*都表示傳遞到腳本的所有參數(shù),在數(shù)組中@和*的應(yīng)用是打印數(shù)組的所有元素。
- #!/bin/bash
-
- city=(Nanjing Beijing Melbourne NewYork)
-
- for i in ${city[@]} #等價(jià)于 for i in ${city[*]}
- do #打印數(shù)組的所有元素
- echo $i
- done
- #!/bin/bash
-
- city[1]="Hong Kong" #用引號(hào)包含空格的字符串
- city[100]=Massachusetts
- city[101]="New York"
- city[10000]=Atlanta
-
- for i in "${city[@]}"
- do
- echo $i
- done
由于city數(shù)組元素包含了空格,因此需要使用引號(hào)將${city[@]}引起來,for循環(huán)和@只打印被賦值的元素而不打印未賦值的元素。
注意:"${city[@]}"將數(shù)組的所有元素分行打印,而"${city[*]}"只能將數(shù)組的所有元素打印在一行內(nèi)且中間以IFS分隔。不用引號(hào)時(shí)${city[@]}和${city[*]}是等價(jià)的,使用引號(hào)時(shí),@和*只是打印數(shù)組的方式存在差異。
(3)數(shù)組的用法
數(shù)組的字符串操作與字符串操作的符號(hào)和意義完全一致,數(shù)組字符串操作特殊之處在于所有的操作都是針對(duì)所有的數(shù)組元素逐個(gè)進(jìn)行的。
- #數(shù)組的字符串操作
- #!/bin/bash
-
- city=(Nanjing Atlanta Massachusetts MaseillesMas)
-
- echo "Extracting Substring" #抽取字串
- echo ${city[*]:0} #抽取整個(gè)數(shù)組 Nanjing Atlanta Massachusetts Marseilles
- echo ${city[*]:1} #抽取從第1個(gè)元素到結(jié)束的數(shù)組 Atlanta Massachusetts Marseilles
- echo ${city[*]:3} #抽取從第3個(gè)元素到結(jié)束的數(shù)組 Marseilles
- echo ${city[*]:0:2} #抽取從第0個(gè)元素開始的兩個(gè)元素 Nanjing Atlanta
- echo
- echo "Removing Substring" #刪除字串
- echo ${city[*]#M*a} #刪除匹配M*a的最短字串 Nanjing Atlanta ssachusetts rseilles
- echo ${city[*]##M*a} #刪除匹配M*a的最長(zhǎng)字串 Nanjing Atlanta chusetts rseilles
- echo
- echo "Replcing Substring" #替換子串功能
- echo ${city[*]/M*s/Year} #替換第1次與M*a匹配的子串 Nanjing Atlanta Year Year
- echo ${city[*]//Mas/Year} #替換所有與Mas匹配的子串 Nanjing Atlanta Yearsachusetts YeareillesYear
- #替換的正則為最長(zhǎng)匹配
數(shù)組也可以存放read命令所讀入的用戶輸入?yún)?shù),declare -a city(并不是必須的)將city申明為數(shù)組,用read -a
city命令將輸入存儲(chǔ)到city數(shù)組之中,輸入以空格分開??梢允褂胾nset city[0]命令清空一個(gè)元素,和unset
city清空整個(gè)數(shù)組。使用${#city[@]}獲取數(shù)組的長(zhǎng)度。
shell數(shù)組的一種重要操作:數(shù)組連接。
- #!/bin/bash
-
- city=(Beijing Nanjing Shanghai)
- person=(Cai [5]=Wu Tang) #數(shù)組不連續(xù)地賦值
-
- declare -a combine #聲明combine數(shù)組
- combine=(${city[@]} ${person[@]}) #combine是數(shù)組city和person的連接,連接操作將不連續(xù)的元素按序存放到combine數(shù)組中
-
- element_count=${#combine[@]} #while循環(huán)輸出combine數(shù)組
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${combine[$index]}" #數(shù)組標(biāo)號(hào)與值的對(duì)應(yīng)關(guān)系
- let "index=$index+1"
- done
- ###################
- echo
- unset combine #清空combine數(shù)組
- combine[0]=${city[@]} #將city數(shù)組賦給combine[0]的一個(gè)元素
- combine[1]=${person[@]} #將person數(shù)組賦給combine[1]的一個(gè)元素
- element_count=${#combine[@]}
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${combine[$index]}"
- let "index=$index+1"
- done
- ###################
- echo
- declare -a subcombine=${combine[1]} #聲明數(shù)組時(shí)賦值
- element_count=${#subcombine[@]}
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${subcombine[$index]}"
- let "index=$index+1"
- done
(4)數(shù)組實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)是指相互之間存在一種或多種特定關(guān)系的數(shù)據(jù)元素的集合,它直接影響到程序的運(yùn)行速度和存儲(chǔ)效率。Shell不直接支持如堆棧、隊(duì)列、鏈表等數(shù)據(jù)結(jié)構(gòu),但可以很容易實(shí)現(xiàn)線性數(shù)據(jù)結(jié)構(gòu)。對(duì)于樹形、圖等復(fù)雜的數(shù)據(jù)結(jié)構(gòu),shell理論上可以實(shí)現(xiàn),但難度角度。
利用數(shù)組實(shí)現(xiàn)堆棧操作。push函數(shù)將字符串壓入堆棧,pop函數(shù)能彈出棧頂元素,status函數(shù)打印當(dāng)前堆棧的狀態(tài)信息。其中shift命令完成兩個(gè)功能:第一,所有位置參數(shù)左移1位,即$2移動(dòng)到$1的位置,$3移動(dòng)到$2的位置,依次類推($0不變);第二,$#變量值減1。
- #!/bin/bash
-
- MAXTOP=50 #堆棧能存放元素的最大值
-
- TOP=$MAXTOP #棧頂指針,初始值是$MAXTOP
-
- TEMP=
- declare -a STACK #全局?jǐn)?shù)組STACK
-
- push() #push進(jìn)棧操作,可同時(shí)將多個(gè)元素壓入堆棧
- {
- if [ -z "$1" ] #無參數(shù),返回
- then
- return
- fi
-
- #for ((i=1; i<=$#; i++))
- until [ $# -eq 0 ] #until循環(huán)將push函數(shù)的所有參數(shù)都?jí)喝攵褩?nbsp;
- do
- let TOP=TOP-1 #棧頂指針減1
-
- STACK[$TOP]=$1
- shift #腳本參數(shù)除$0外左移1位,$#參數(shù)總個(gè)數(shù)減1
- done
-
- return
- }
-
- pop() #pop出棧操作,執(zhí)行pop函數(shù)使棧頂元素出棧
- {
- TEMP=
-
- if [ "$TOP" -eq "$MAXTOP" ] #若堆棧為空,返回
- then
- return
- fi
-
- TEMP=${STACK[$TOP]} #棧頂元素出棧
- unset STACK[$TOP]
- let TOP=TOP+1 #棧頂指針加1
- return
- }
-
- status() #顯示當(dāng)前堆棧內(nèi)的元素,以及TOP指針和TEMP變量
- {
- echo "==========STACK=========="
- for i in ${STACK[@]}
- do
- echo $i
- done
- echo "Stack Pointer=$TOP"
- echo "Just popped \""$TEMP"\" off the stack"
- echo "=========================="
- }
-
- push one #1個(gè)元素入棧
- status #顯示狀態(tài)
- push two three four #3個(gè)元素入棧
- status
-
- pop #出棧
- pop
- status
- push five six
- status
利用一維數(shù)組模擬實(shí)現(xiàn)二維數(shù)組,二維數(shù)組仍存儲(chǔ)在一維數(shù)組中,只是通過行號(hào)和列號(hào)計(jì)算出數(shù)組的索引而已??梢圆捎迷摲椒ㄊ箂hell腳本語言用于定義二維數(shù)組和矩陣。
- #創(chuàng)建一個(gè)二維數(shù)組,并以逐行打印及旋轉(zhuǎn)45度打印的兩種方式將它打印出來
- #!/bin/bash
-
- #定義行數(shù)、列數(shù),及數(shù)組名
- ROW=5
- COL=5
- declare -a MATRIX #申明MATRIX數(shù)組
-
- load_alpha ()
- {
- local rc=0
- local index
-
- #for循環(huán)將A-Y這25個(gè)字符存儲(chǔ)到MATRIX數(shù)組
- for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y
- do
- local row=`expr $rc / $COL`
- local column=`expr $rc % $ROW`
- let "index = $row * $ROW + $column"
- MATRIX[$index]=$i
- let "rc += 1"
- done
- }
-
- print_alpha ()
- {
- local row=0
- local index
-
- #逐行打印MATRIX數(shù)組
- while [ "$row" -lt "$ROW" ]
- do
- local column=0
- echo -n " "
- while [ "$column" -lt "$COL" ]
- do
- let "index = $row * $ROW + $column"
- echo -n "${MATRIX[index]} "
- let "column += 1"
- done
- let "row += 1"
- echo
- done
- echo
- }
-
- filter () # 過濾掉負(fù)的數(shù)組下標(biāo).
- {
- echo -n " " # 產(chǎn)生傾斜.
- # 解釋一下, 這是怎么做到的.
-
- if [[ "$1" -ge 0 && "$1" -lt "$ROW" && "$2" -ge 0 && "$2" -lt "$COL" ]]
- then
- let "index = $1 * $ROW + $2"
- # 現(xiàn)在, 按照旋轉(zhuǎn)方向進(jìn)行打印.
- echo -n " ${MATRIX[index]}"
- # alpha[$row][$column]
- fi
- }
-
- rotate () # 將數(shù)組旋轉(zhuǎn)45度 --
- { #+ 從左下角進(jìn)行"平衡".
- local row
- local column
-
- for (( row = ROW; row > -ROW; row-- ))
- do
- for (( column = 0; column < COL; column++ ))
- do
- if [ "$row" -ge 0 ]
- then
- let "t1 = $column - $row"
- let "t2 = $column"
- else
- let "t1 = $column"
- let "t2 = $column + $row"
- fi
- filter $t1 $t2 # 將負(fù)的數(shù)組下標(biāo)過濾出來
- done
-
- echo; echo
- done
- }
-
- #下面利用上述函數(shù)創(chuàng)建二維數(shù)組,逐行和旋轉(zhuǎn)45°打印數(shù)組
- load_alpha # 加載數(shù)組
- print_alpha # 打印數(shù)組
- rotate # 逆時(shí)針旋轉(zhuǎn)45°打印
三、總結(jié)
(1)別名、列表及數(shù)組這三個(gè)知識(shí)點(diǎn)是相對(duì)獨(dú)立的,可分開理解。
(2)數(shù)組是重點(diǎn),會(huì)使用數(shù)組字符串的操作,以及利用數(shù)組實(shí)現(xiàn)堆棧和二維數(shù)組等數(shù)據(jù)結(jié)構(gòu)。
|