對於一臺計算機而言,其硬件受系統內核的控制,使用者想要控制計算機,就必須有與系統內核進行通信的手段。而shell就是使用者與計算機進行通信的手段之一。從命名上看,shell實際上是相對於kernel(內核)而言,指系統與外界(使用者)進行接觸的部分,一個提供系統功能給用戶使用的軟件,它接受來自用戶的指令,而後調用相應的應用程序。
爲了知足不一樣的需求,shell提供了兩種執行命令方式:linux
ryeshen@~$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh /bin/ksh /bin/zsh而linux默認是用的解釋器是bash。在腳本頭能夠聲明本腳本所使用的解釋器,
單引號:不保留特殊符號的功能,括號內內容僅做爲純文本進行使用。
如:正則表達式
ryeshen@~$ echo "I am $name" I am someone ryeshen@~$ echo 'I am $name' I am $name
反引號:引號內內容會被做爲命令先被執行,命令的結果做爲引號的輸出。$()的效果與之相同
如:shell
ryeshen@~$ echo I am `pwd` I am /home/asl ryeshen@~$ echo I am $(pwd) I am /home/asl
ryeshen@~$ echo `echo \$SHELL` /bin/bash ryeshen@~$ echo $(echo \$SHELL) $SHELL ryeshen@~$ echo `echo \\$SHELL` $SHELL ryeshen@~$ echo $(echo \\$SHELL) \/bin/bash ryeshen@~$ echo `echo \` > ryeshen@~$ echo $(echo \\) \參考的文章的解釋是「反引號齊自己就對\進行了轉義,保留了齊自己意思,若是咱們想在反引號中起到\的特殊意義,咱們必須使用2個\來進行表示」。
#shell腳本中#表示行註釋 array=(0 1 2 3 4) array[101]=101 #直接經過 數組名[下標] 就能夠對其進行引用賦值。 #若是下標不存在,自動添加新一個數組元素 unset array[101] #使用unset清除指定值 unset array #使用unset清除整個數組
echo ${array[2]} #使用下標獲取值 echo ${a[@]} #使用@或*獲取數組全部值 echo ${a[*]}
輸出結果:數組
2 0 1 2 3 4 0 1 2 3 4
#${數組名[@或*]:起始位置:長度} newArray=(${array[@]:1:3}) #先截取數組"1 2 3",再將截取到的數組賦給newArray
for a in ${arr[@]} do echo "$a" done
a="one,two,three,four" OLD_IFS="$IFS" #使用臨時變量保存環境變量IFS的值 IFS="," #給環境變量IFS賦值,這個值用來切割字符串 arr=($a) #字符串切分 IFS="$OLD_IFS" #還原IFS
if …; then … elif …; then … else … fi注意格式中分號;的使用。
ryeshen@~$ if echo "123"; then > echo "123" > fi 123 123
( ): 1. 用於數組的初始化
2. 指令羣組(command group),即用括號將一組命令包括起
來,這組命令共用一個shell子進程,所以能夠分享自定義變量等。
(( )): 至關於命令let,用於算數運算。舉個例子:bash
ryeshen@~$ ((a=1+1)); echo $a 2 ryeshen@~$ ((a=1+1)); echo $a 2
[ ]和[[ ]]的區別:
如上所說,[實際上是一個指令,所以使用判斷中字符串時最好用雙引號括住,
且>、<必須改寫成>和\<(>,<是重定向符)。
另外,在使用&&和||時,必須寫成 [ cond1 ] && [ cond2 ] 的形式。
[[ ]]則是bash的關鍵字。能夠直接使用>、<、&&、||,如[[ a>1 && b>2 ]]。
[[ ]]中字符串未雙引號括住的話,能進行正則表達式匹配。如:函數
ryeshen@~$ [[ ab == a* ]] && echo "ok" ok
if語句支持的運算符/操做符:(能夠理解爲是[指令的參數,就像rm -rf同樣)學習
for var in …; do do something done for (( cond1; cond2; cond3 )) do do something done
應用示例:ui
#輸出1 2 3 4 …… 10 for i in $(seq 10); do #這裏是用seq指令生成了"1 2 3 …… 10"的字符串 echo $i; done; #判斷輸入的字符串是否是文件名 for file in $*; do # $*指從命令行讀入的參數,如輸入"test.sh a.xml b.txt c.pdf",則$*=(a.xml b.txt c.pdf) if [ -f "$file" ]; then echo "INFO: $file exists" else echo "ERROR: $file not exists" fi done;
while [ cond1 ] && { || } [ cond2 ] …; do do something done
until [ cond1 ] && { || } [ cond2 ] …; do do somethingdone應用示例:
# 逐行輸出/etc/hosts文件內容 while read line; do echo $line; done < /etc/hosts; # 這裏能讀入/etc/hosts,是由於<將文件重定向到read指令
case var in pattern 1 ) … ;; pattern 2 ) … ;; *) … ;; esac
另外提一下shfit,它能夠將入參左移,即進行賦值:$1=$2;$2=$3;$3=$4……
case能夠與shfit結合使用,用於根據入參進行處理,舉例以下:
shell腳本test.sh:spa
#!/bin/bash while [ $# -gt 0 ]; do case $1 in -a) shift; echo a-$1; shift; ;; -b|-d) shift; echo bd-$1; shift; ;; -c) shift; echo c-$1; shift; ;; *) echo unkown; shift; esac done
輸出:命令行
ryeshen@~$ ./test.sh -a 1 -c 2 -b 3 -d 3 a-1 c-2 bd-3 bd-3
functionname() { do something } function func() { do something }
func param1 param2 ... # 函數內使用$#,$1等方式獲取參數屬性和參數,與腳本獲取入參相似
func ret=$? #使用$?獲取函數的執行結果 ret=`func` #使用反單引號執行函數並將返回值賦值給變量
+ 腳本中定義的變量可在函數中使用
+ 函數中可用local關鍵字聲明屬於本身的,不被外部可見的局部變量
學習過shell的基礎知識後,最大的感覺是原覺得是 shell腳本的特殊用法事實上是有規律可推理的。在此以前,雖然知道[]兩邊要加空格、使用while read $line;do……done < a.txt能夠逐行讀入文件等零碎的知識點,但只是知其然殊不知其因此然。瞭解了shell的特殊符號的含義後,才發現這些東西並不是只能靠死記硬背,而是有規則可循的。