!腳本執行與調試
1、絕對路徑執行,要求文件有執行權限
2、以sh命令執行,不要求文件有執行權限
3、.加空格或source命令執行,腳本將在當前shell中執行
4、檢查腳本語法
bash -v test.sh
5、跟蹤腳本執行
bash -x test.sh
!環境腳本執行規則
用戶登錄:/etc/profile、~/.bash_profile、~/.bash_login、~/.profile
用戶注銷:~/.bash_logout
執行新shell: /etc/bash.bashrc、~/.bashrc
執行script(使用#!/bin/bash):如指定BASH_ENV的值,則執行其指定的啟動文件
執行script(使用#!/bin/sh):不調用任何環境腳本
!基本語法
1、腳本程序以#!/bin/bash 開始。以告之系統腳本以何種shell執行。
2、以#開頭的行被視為注解,執行時自動忽略。
3、每行不得多於255個字節,可在行末加上反斜杠的方式拆分單行內容到多行中。
例如:
test1=abcdefg\
hij\
klmnopq\
rstuvwxyz
4、多命令以分號分隔時,命令從左至右依次執行。
例如: whoami;w
5、多命令以&&分隔時,命令從左至右按前面命令執行成功后再執行下個命令的原則依次執行。
例如:make && make install
6、多命令以||分隔時,命令從左至右按前面命令執行失敗后再執行下個命令的原則依次執行。
7、多個命令以分號分隔放置()中,則會啟用子shell並執行。
例如:(mkdir testdir;cd testdir;touch testfile)
8、多個命令以分號分隔放置{}中,則會在當前shell中執行。需要注意的是命令和{}必須有空格間隔,並且最后一條命令也必須加分號。
例如:{ mkdir testdir;cd testdir;touch testfile; }
9、被反引號`括起來的命令或$(命令),shell將直接引用執行結果。
例如:
test=`date`
test=$(date)
10、可以將算術運算式以$[ 算術運算式 ]的形式進行求值。注意算術運算式和[]必須有空格分隔,此方法只支持整型運算。
例如:test=$[ 32 * 17 ]
11、使用$((運算式))的形式也可以進行算術運算求值,並且可以進行布爾運算。
例如:test=$(( 32 * 17 ))
12、使用let 運算式也能進行算術運算,算術式各元素間不得有空格,否則應將算術式用引號括起來。
例如:let ++test
13、任何命令執行后均會返回一個取值范圍在0~255之間的整型返回碼。主要值含義如下:
0:正常結束
1:通用執行錯誤
2:誤用shell命令
126:命令不可執行
127:命令未找到
128:無效退出參數
130:被ctrl-c強行中止
255:退出狀態碼越界
shell script默認返回最后一條命令的返回碼。可以使用exit退出script執行並返回指定的返回碼。
例如:exit 15
通過$?這個系統變量可以獲取上一條命令的返回碼。
例如:
sync
echo $?
14、通過getopts命令獲取命令行選項。
語法為:getopts 選項行 選項變量。
選項行由各選項的單一字符組成,如某選項字符需要參數,則在選項字符后加冒號。調用時此選項后無參數的話系統會提示錯誤,如不希望出現提示則應在選項行最前面加上冒號。系統會將參數存入OPTARG變量。
例如:
#!/bin/bash
while getopts :a:bc opt
do
case $opt in
a)
echo "選項a,后跟參數:$OPTARG";;
b)
echo "選項b";;
c)
echo "選項c";;
*)
;;
esac
done
15、利用mktemp建立臨時文件
語法為:mktemp 選項 臨時文件模板
如果建立成功返回0。
臨時文件模板格式形式如:/tmp/test.XXXXXX或/usr/ttt/tttt.XXXXXX,文件名末6個字符必須為XXXXXX.生成成功后會由系統代替為隨機6個字符。
選項-q 不產生錯誤信息。
選項-p 指定建立臨時文件的父級目錄,父級目錄必須已存在。例如:mktemp -p /usr/tmp tf.XXXXXX
選項-t 按環境變量TMPDIR變量中指定的父級目錄建立臨時文件,如變量未定義,則父級目錄為/tmp
選項-d 建立的是臨時目錄。
直接執行mktemp,會在/tmp目錄下建立tmp.XXXXXX形式的臨時文件,文件名末6個字符為隨機字符。可使用下面方式獲取生成的文件名。
tmpfile=$(mktemp)
!變量
1、變量命名可使用英文字母、數字和下划線,必須以英文字母開頭,區分大小寫。
2、每個shell都擁有自己的變量定義,彼此互不影響。
3、變量直接以等號賦值,注意等號兩邊不可留空,若等號右側有空格,賦值要用引號括起來。
例如:
test=1
test='hello world'
4、通過在變量名前加$的方式獲取變量的值。或者使用${變量名}的形式,以利於變量名和緊接其后的字母或下划線進行區分。
例如:${test}
5、通過${#變量}的形式獲取變量值字串的長度。
例如:test='12345';echo ${#test} #輸出5
6、可以將變量聲明為全局變量,全局變量作用范圍包含所有shell。命令為:export 變量名
例如:export test
7、使用unset注銷變量,需要注意的是注銷僅局限於當前shell,即使全局變量也一樣。unset -v 變量名
例如:unset test
8、清空變量的方式:變量名=
例如:test=
9、數組變量
使用變量名=(成員值1 成員值2 ...)的形式賦值,成員值之間以空格分隔。
例如:$testarray=(1 2 'abcd' 38)
數組值獲取使用$變量名[下標]的形式,下標從0計數。
例如:$testarray[2]
通過${變量名[@]}或${變量名[*]}可以獲取數組所有成員,區別是,前者是各成員單獨輸出,后者是將所有成員以一個字符串的形式整體輸出。
通過${#變量名[@]}或${#變量名[*]}可以獲取數組成員數量。例如:${#testarray[@]}。
需要注意unset某個數組成員后,此成員的下標並不移除。
例如:
testarray=(1 2 3 4 5 6)
unset testarray[2]
echo testarray[2] #無值輸出
echo testarray[3] #輸出4
數組可以動態添加成員,例如:testarray=($testarray[@] 7);
如果數組下標也是變量,則應用{}將數組變量括起來,例如:i=1;echo ${testarray[$i]}
10、使用readonly可以聲明一個變量為只讀屬性。
例如:
readonly test #聲明test變量為只讀
readonly -f testfunc #聲明testfunc函數為只讀
readonly -a testarray #聲明testarray數組為只讀
11、bash shell可以通過declare進行變量聲明。
例如:
declare -a testarray #定義一個數組變量
declare -i test #定義一個整型變量
declare -r test #定義一個只讀變量
declare -t test #設定變量具有trace屬性
declare -x test #定義一個環境變量
12、shell提供一組命令檢測變量是否存在或是否為空,根據檢測結果執行對應操作,列表如下:
${變量:-字串} 如果變量存在且有值,返回變量值,否則返回字串內容。
${變量:=字串} 如果變量存在且有值,返回變量值,否則將字串賦給變量,並返回字串內容。
${變量:?字串} 如果變量存在且有值,返回變量值,否則顯示將字串作為錯誤信息顯示,並退出script執行。
${變量:+字串} 如果變量存在且有值,返回字串內容,否則返回空值。
注:去掉命令中的:,則只檢測變量是否存在,不檢測是否為空。
13、變量可以通過${變量:起始位置:截取長度}的形式,過行取子串操作。如果從起始位置取至字串尾,則截取長度可以省略。
例如:
test="123456789"
echo ${test:1:3} #輸出234
echo ${test:2} #輸出3456789
14、變量可以通過命令對其字串值進這行刪除替換處理,列表如下:
${變量#匹配式} 根據匹配式從左最短匹配子串並刪除。
${變量##匹配式} 根據匹配式從左貪婪匹配子串並刪除。
${變量%匹配式} 根據匹配式從右最短匹配子串並刪除。
${變量%%匹配式} 根據匹配式從右貪婪匹配子串並刪除。
${變量/匹配式/替換串} 根據匹配式從左匹配第一個子串替換成替換串。
${變量//匹配式/替換串} 根據匹配式匹配所有子串替換成替換串。
${變量/#匹配式/替換串} 根據匹配式從左匹配第一個子串替換成替換串。
${變量/匹配式/} 根據匹配式從左匹配第一個子串並刪除。
${變量//匹配式/} 根據匹配式從右匹配所有子串並刪除。
${變量/#匹配式/} 根據匹配式從左匹配第一個子串並刪除。
${變量/%匹配式/} 根據匹配式從右匹配所有子串並刪除。
15、利用eval實現動態變量功能,動態變量的變量名由另一個變量的值構成。
示例:
#設n1變量的值為另一個變量的名稱
n1="n2"
#給動態變量n2賦值
eval ${n1}=abc
echo "$n1=$n2" #輸出n2=abc
#以動態方式將動態變量n2的值賦給變量t
eval t=\$${n1}
echo "t=$t" #輸出t=abc
!流程控制命令
1、if 條件轉向命令
基本格式:
if 命令A
then
命令
...
else
命令
...
fi
嵌套格式:
if 命令A
then
命令
...
elif 命令B
then
命令
...
elif 命令C
then
命令
...
...
...
fi
如果if后面跟的命令執行返回碼為0則執行then后面的命令,否則執行else后面的命令。
if和then可以放到一行,前提是if后跟的命令加分號結尾。
例如:
if test -r /etc/passwd; then cat /etc/passwd; fi
2、case條件選擇命令
基本格式:
case 變量 in
匹配串1)
命令
...
;;
匹配串2)
命令
...
;;
... ...
... ...
匹配串n)
命令
...
;;
*)
命令
...
;;
esac
匹配串的格式:
單純字符串 完全匹配。
* 任意長度的任意字串,包括空串。例如:j*k,匹配jack、jak。
? 單個字符。例如:j??k,匹配jack,但不匹配jak。
[] 字符集.例如:[a-c]OK,匹配aOK、bOK、cOK。
| 匹配多個匹配串。例如:j??k|[a-c]OK|jak。
如果打開extglob選項,則能支持高級匹配。shopt -s extglob
?(匹配串) 匹配0個或1個括號里的匹配串。
*(匹配串) 匹配0個以上括號里的匹配串。
+(匹配串) 匹配1個括號里的匹配串。
@(匹配串) 匹配括號里的匹配串其中的一項。
!(匹配串) 匹配非括號里的匹配串。
3、for循環命令
基本格式1:
for 變量 in IFS分隔符定義的字串
do
命令
...
done
處理基本字串:
for i in 1 2 3 4 5 6 7 8 9
do
echo $i
done
從文件取串處理:
for i in $(cat /etc/passwd)
do
IFS_old=IFS
IFS=':'
for j in $i
do
echo "$j "
done
echo "---------------------------"
IFS=IFS_old
done
以通配符遍歷目錄:
for i in /etc/*
do
if [ -f "$i" ]; then
echo "$i 是文件"
fi
done
基本格式2:
for ((初始化;結束條件判斷;參數變更))
do
命令
...
done
此格式類似C語言,具體定義不再闡述。僅舉一例
for ((i=1,j=1;(i+j)<=100;i=i+1;j=j+1))
do
echo "$i,$j"
done
4、while循環命令
基本格式:
while 條件判斷
do
命令
...
done
當條件符合條件判斷式時執行循環體。
基本應用:
i=0
while (($i<10))
do
echo $i
i=$(($i+1))
done
從文件讀取內容:
while read line
do
echo $line
done < "/etc/passwd"
無限循環:
while :
do
sleep 5
done
5、until循環命令
基本格式:
until 條件判斷
do
命令
...
done
當條件不符合條件判斷式時執行循環體。
6、select菜單選擇命令
基本格式:
select 變量 in IFS定義的分隔符分隔的字串行
do
命令
... ...
done
將字串以IFS定義的分隔符為界分解成若干項,編號后列表顯示輸出,並將環境變量PS3定義的內容作為選擇提示符顯示。根據用戶選擇進行相應的操作。
例如:
PS3="請您選擇:"
select sel in "測試 1" "測試選擇2" "測試選擇 3" "退出選擇"
do
case $sel in
"測試 1")
echo "測試 1";;
"測試選擇2")
echo "測試 2";;
"測試選擇 3")
echo "測試 3";;
*)
break
;;
esac
done
7、break命令,中止並跳出當前循環體。
8、continue命令,直接結束此輪循環,繼續下輪循環。
9、條件判斷命令
條件判斷命令是與流程控制語句配合使用的命令。
命令格式: test 條件判斷式
返回條件判斷式的值,條件成立返回0,否則返回非0值。
通常使用[ 條件判斷式 ]的格式代替test命令,注意條件判斷式與[]必須有空格分開。
參與判斷的變量必須已初始化且非空。
例如:[ -e ~/.bashrc ]
條件判斷支持復合條件判斷:
A、與判斷
使用&&分隔兩條判斷命令。
例如:[ -e ~/.bashrc ] && [ ~/.bashrc -nt /etc/passwd ]
B、或判斷
使用||分隔兩條判斷命令。
例如:[ -e ~/.bashrc ] || [ ~/.bashrc -nt /etc/passwd ]
C、非判斷
使用!符號進行非判斷。
例如: [ ! -e ~/.bashrc ]
條件判斷式包括數值判斷、字串判斷、文件判斷和復合判斷四類操作,分別定義如下:
A、數值判斷
[ n1 -eq n2 ] #判斷n1==n2
[ n1 -ge n2 ] #判斷n1>=n2
[ n1 -gt n2 ] #判斷n1>n2
[ n1 -le n2 ] #判斷n1<=n2
[ n1 -lt n2 ] #判斷n1<n2
[ n1 -ne n2 ] #判斷n1!=n2
注意:數值判斷僅支持整型。
B、字串判斷
[ str1 = str2 ]
[ str1 != str2 ]
[ str1 < str2 ]
[ str1 > str2 ]
[ -n str1 ] #判斷str1長度是否非0
[ -z str1 ] #判斷str1長度是否為0
注:如果字串有空格,應將其用引號括起來。
C、文件判斷
[ -d file ] #判斷目錄file是否存在
[ -e file ] #判斷file是否存在
[ -f file ] #判斷文件file是否存在
[ -r file ] #判斷file是否存在並可讀
[ -s file ] #判斷file是否存在並非空
[ -w file ] #判斷file是否存在並可寫
[ -x file ] #判斷file是否存在並可執行
[ -O file ] #判斷file是否存在並屬於當前用戶
[ -G file ] #判斷file是否存在且默認組於當前用戶所屬組是否相同
[ file1 -nt file2 ] #判斷file1是否比file2新
[ file1 -ot file2 ] #判斷file1是否比file2舊
D、復合判斷
-a 與操作,例如:[ -e file -a -r file ]
-o 或操作,例如:[ -e file -o -r file ]
條件判斷可以通過(())使用標准數學運算符進行數值賦值運算和判斷。
例如:
test=3
if (( $test * 3 > 1 ));then
echo $test
else
echo $(( ++test ))
fi
條件判斷可以通過[[]]代替test進行字串比較,同時還提供了正則匹配功能。注意判斷式和[[、]]以及運算符之間要用空格分隔。
例如:
test="aaabbb123"
if [[ $test == 'a*' ]];then
echo ok
fi
!函數
1、基本格式
function 函數名()
{
命令
... ...
}
2、基本用法
關鍵詞function和函數名后的括號可以單獨省略,但不可同時省略。
默認以最后執行命令的返回值代表函數的返回碼。可以使用return命令立即結束函數執行,並以return后指定的值做為返回碼。如果return未指定值,則返回0。
函數需要在首次調用前定義,建議在程序最前面定義。
可以將函數統一定義在單獨文件中,再以source或. (注意.后面有空格)的形式被其他程序調用。為了不產生沖突,建議函數包中定義的函數名以下划線開頭。
函數內局部變量應以local關鍵詞定義。
函數直接以函數名調用,如需傳入參數則在函數名加空格后跟寫,多個參數以空格分隔。
函數使用和$n的形式調用傳入的位置參數,此時主程序的位置參數不受影響。
函數定義后支持動態調用。
例如:
func.sh
#!/bin/bash
_testfunc()
{
if (( $1 > $2 ));then
echo "$1 > $2"
elif (( $1 == $2 ));then
echo "$1 = $2"
else
echo "$1 < $2"
fi
return 10
}
main.sh
#!/bin/bash
. func.sh
_testfunc 32 24
_testfunc 15 15
_testfunc 1 12
#動態調用示例
s="_testfunc"
`$s 12 12`
!常用內置命令
1、echo
顯示信息,自動換行
echo -n
取消自動換行
echo -e
字串中控制符生效,比如\n
echo顯示的信息如果包含空格則應用單引號或雙引號括起來。
用雙引號括起來的內容,會對其中的變量取值、運算式計算結果、獲取命令執行結果、轉義符進行轉義后再輸出。
單引號對括起來內容不做任何轉換直接輸出。
例如:echo "it's me" #輸出 it's me
test=lykyl;echo '$test' #輸出 $test
如果顯示信息包括變量則獲取變量值后再與字串組合后顯示。
例如:test=lykyl;echo "hello $test" #輸出 hello lykyl
如果確實要輸出$字符,可以通過轉義符或將字串用單引號括起來。
例如:test=lykyl;echo -n 'hello $test';echo "\$test" #輸出 hello $test $test
2、:
回傳0
3、eval
解析字串參數,以命令形式執行
4、source
在當前shell中執行指定shell程序。
例如:source func.sh
6、read
read 變量名
獲取用戶輸入,並將輸入內容存入命令后面的變量中。如果不指定變量,則默認存入REPLY這個變量中。
read -p '提示信息' 變量名
顯示提示信息后,等待用戶輸入。
read -a 變量名
接受以空格分隔的一組值,存入指定的變量中。
read -r 變量名
read命令默認去掉轉義字符前面的反斜杠,例如,輸入\n存入變量后只有n。增加-r選項后,read命令將接受轉義字符,不做過濾。
read -t 等待時長 變量名
設置read等待輸入的時長,超時后read將返回一個非零值。
read -s 變量名
隱藏用戶輸入內容在屏幕上的回顯。
7、exec
exec 命令
執行命令,取代目前shell。
exec < 文件名
轉向輸入,將通過標准輸入讀取數據的方式變成從指定文件獲取。
8、eval
執行命令后面參數組合成的指令。
例如:
showfile='/etc/passwd'
eval "cat $showfile"
9、expr
返回算術運算式的值,需要注意運算式元素間應以空格分隔,遇到與系統控制符沖突的操作符要加轉義。
例如:
expr 1 + 1
expr 2 \* 3
10、bc
計算器
可以通過bc使shell script處理浮點運算。bc內置變量scale控制小數點后精確位數。
A、簡單運算
通過管道將多個運算式以分號分隔后傳給bc,從左至右依次執行后將最右側運算式的值輸出。
echo "運算式1;運算式2;..."|bc
例如:
num=33
var=`echo "scale=3;v=5*$num;v3=v/4;v3+1"|bc`
B、復雜運算
通過內聯輸入重定向進行更復雜運算操作。
例如:
num=33
var=`bc <<EOF
scale=2
v1=15.5
v2=34*v1
v3=$num*v2+3
v1*(v2+v3/2)
EOF
`
!常用系統變量
1、$0
當前執行的shell script文件名(帶完整路徑)
2、$1 ~ $n
依次存放shell script的命令行參數,數值大於9時必須要用{}括起來,比如${10}。
命令行參數可以通過shift命令進行位移操作,位置參數根據shift命令指定的數值往前移動,如不指定移動值,則移動1次。例如:
#!/bin/bash
echo "所有入參:$@"
while shift
do
[ -n "$1" ] && echo $1
done
3、$*
將所有命令行參數做為一個字符串存入此變量。
4、$@
將所有命令行參數做為一個字符串數組,每個參數為一個成員變量,存入此變量。
5、$#
命令行參數的個數。
6、$?
上一條命令執行后的返回碼。
7、$$
當前執行的shell script進程編號。
8、$!
上一個后台程序的進程編號。
9、$_
script執行時,存放bash的絕對路徑。
bash交互時,存放上一個命令最后一個命令行參數。
郵件檢測時,存放郵件文件名。