五、BASH SHELL編程:
1. 初始化順序: /etc/profile ( ~/.bash_profile | ~/.bash_login | ~/.profile ) ~/.bashrc
2. set -o allexport 當前shell變量對其所有子shell都有效.
set +o allexport 當前shell變量對其所有子shell都無效.
set -o noclobber 重定向輸出時,如果輸出文件已經存在則提示輸出失敗, date > out; date > out, 第二次操作失敗
set +o noclobber 缺省shell行為. date > out; date > out, 第二次操作成功
shopt -s extglob 使用擴展通配符,如 abc?(2|9)K, abc*([0-9]), abc+([0-9]), no@(thing|body), no!(thing|body)
其中?,*,+,@和!都是用於修飾後面的()的.
3. 變量聲明: declare, 在賦值的時候等號的兩邊不需要空格. variable=value.
declare -r variable=value 聲明只讀變量.
declare -x variable=value 相當於export variable=value.
數組聲明:
declare -a variable=(1 2 3 4)
or
name=(tom tim helen)
or
x[0]=5
x[4]=10
數組的聲明可以不是連續的, 這一點和awk中的數組比較類似.
e.g.
/> declare -a friends
/> friends=(sheryl peter louise)
/> echo ${friends[0]}
sheryl
/> echo ${friends[1]}
peter
/> echo ${friends[2]}
louise
/> echo ${friends[*]}
shery1 peter louise
/> echo ${#friends[*]}
3
unset friends
/> declare -a states=(ME [3]=CA [2]=CT)
/> echo ${states[*]}
ME CA CT
/> echo ${#states[*]}
3
/> echo ${states[0]}
ME
/> echo ${states[1]}
/> echo ${states[2]}
CT
/> echo ${states[3]}
CA
unset states
4. 函數聲明:
function greeting
{
echo "Hi $1 and $2";
}
/> greeting tom joe
Hi tom and joe
unset -f greeting
5. printf其參數類型類似於awk的printf.
6. 變量擴展修改符:
${variable:+word}
if (NULL != variable)
echo word
else
echo $variable
e.g.
/> unset var_name
/> var_name=
/> echo ${var_name:+AA}
/> var_name=BB
/> echo ${var_name:+AA}
AA
/> echo $var_name
BB
${variable:-word}
if (NULL == variable)
echo word
else
echo $variable
e.g.
/> unset var_name
/> var_name=
/> echo ${var_name:-AA}
/> AA
/> var_name=BB
/> echo ${var_name:-AA}
BB
/> echo $var_name
BB
${variable:=word}
if (NULL == variable)
{
variable=word
echo word
}
else
{
echo $variable
}
e.g.
/> unset var_name
/> echo ${var_name:=AA}
AA
/> echo $var_name
AA
/> echo ${var_name:=CC}
AA
/> echo $var_name
AA
${variable:offset}/${variable:offset:length}
e.g.
/> var_name=notebook
/> echo ${var_name:0:4}
/> note
/> echo ${var_name:4:4}
/> book
/> echo ${var_name:2}
/> tebook
/> echo ${var_name:0}
/> notebook
${variable%pattern} 從variable尾部開始,最小化的刪除pattern
e.g.
/> variable="/usr/bin/local/bin"
/> echo ${variable%/bin*}
/usr/bin/local
${variable%%pattern} 從variable尾部開始,最大化的刪除pattern
/> variable="/usr/bin/local/bin"
/> echo ${variable%%/bin*}
/usr
${variable#pattern} 從variable頭部開始,最小化的刪除pattern
/> variable="/home/lilliput/jake/.bashrc
/> echo ${variable#/home}
/lilliput/jake/.bashrc
${variable##pattern} 從variable頭部開始,最大化的刪除pattern
/> variable="/home/lilliput/jake/.bashrc
/> echo ${variable##*/}
.bashrc
${#pattern} 返回patter的字符數量.
/> variable=abc123
6
7. 引用:
\: 可以史shell中的元字符無效, 如?, < >, \, $, *, [ ], |, ( ), ;, &, { }
': 單引號可以史其內的所有元字符無效, 也包括\.
": 雙引號也可以史其內的所有元字符無效, 變量和命令替換除外. 如 echo "What's time? $(date)", 這裡date命令將被執行.
8. 命令替換:
variable=$(date) or variable=`date`
variable=`basename \`pwd\`` or variable=$(basename $(pwd)) 命令替換可以嵌套, 第一種方法中,嵌套的命令必須使用\進行轉義.
eval: 可以進行命令行求值操作.
e.g.
/> set a b c d
/> echo The last argument is \$$#
/> The last argument is $4
/> eval echo The last argument is \$$#
/> The last argument is d
9. 數學計算:
/> echo $[5+4-2]
7
/> echo $[5+2*3]
11
/> echo $((5+4-2))
7
/> echo $((5+2*3))
11
/> declare -i num //必須聲明-i, 以表示整型變量.
/> num=5+5
/> echo $num
10 //如果沒有聲明declare -i, 則返回5+5.
/> num=5 + 5
-bash: + 5: command not found.
/> num="5 + 5"
/> echo $num
10
/> num=4*6
/> echo $num
24
使用不同進制(2~36)表示數字.
/> declare -i x=017
/> echo $x
15
/> x=2#101
/> echo $x
5
/> x=8#17
/> echo $x
15
/> x=16#b
/> echo $x
11
let專門用於數學運算的bash內置命令.
/> let i=5
/> let i=i+1
/> echo $i
6
/> let "i = i + 2"
/> echo $i
8
/> let "i+=1"
/> echo $i
9
10. 讀取用戶輸入(read)命令:
/> read answer
yes
/> echo "$answer is the right response."
yes is the right reponse.
/> read first middle last
Jon Jake Jones
/> echo "Hello $first"
Hello Jon
/> read //如果沒有變量時, $REPLY是缺省變量.
the Chico Nut factory
/> echo "I guess $REPLY keeps you busy!"
I guess the Chico Nut factory keeps you busy!
/> read -p "Enter your job titile: "
Enter your job title: Accountant
/> echo "I thought you might be an $REPLY".
I thought you might be an accountant.
/> read -a friends
Melvin Tim Ernest
/> echo "Say hi to ${friends[2]}
Say hi to Ernest.
/> echo "Say hi to ${friends[$[${#friends[*]}-1]]}"
Say hi to Ernest.
11. 條件結構和流控制:
1) 條件判斷方法: test, [ ], [[ ]], (( )), 當$?為0時表示成功和true, 否則失敗和false.
/> name=tom
/> test $name != tom
/> echo $?
1 //Failure
/> [ $name=Tom ]
/> echo $?
0
/> [ $name = [Tt]?? ] //[]和test不允許使用通配符.
/> echo $?
1
/> x=5
/> y=20
/> [ $x -gt $y ]
/> echo $?
1
/> [ $x -le $y ]
/> echo $?
0
/> name=Tom
/> friend=Joseph
/> [[ $name == [Tt]om ]]
/> echo $?
0
/> [[ $name == [Tt]om && $friend == "Jose" ]]
/> echo $?
1
/> x=2
/> y=3
/> (( x > 2))
/> echo $?
1
/> (( x < 2))
/> echo $?
1
/> (( x == 2 && y == 3))
/> echo $?
0
2) test命令操作符:
字符串判斷:
[ string1 = string2 ] or 兩個字符串相等時返回true.
[ string1 == string2 ]
[ string1 != string2 ] 兩個字符串不等時返回true.
[ string ] string非空時返回true.
[ -z string ] 為空時返回true.
[ -n string ] 為非空時返回true.
邏輯判斷:(cond1可以包含元字符)
[ string1 -a string2 ] or string1和string2都非空時
[[ cond1 && cond2 ]] cond1和cond2都為true
[ string1 -o string2 ] or string1或string2為非空時
[[ cond1 || cond2 ]] cond1或cond2為true.
[ ! string ] or string為空
[[ !cond ]] cond為false.
整數判斷:
[ int1 -eq int2 ] int1等於int2
[ int1 -ne int2 ] int1不等於int2
[ int1 -gt int2 ] int1大於int2
[ int1 -ge int2 ] int1大於等於int2
[ int1 -lt int2 ] int1小於int2
[ int1 -le int2 ] int1小於等於int2
文件判斷
[ file1 -nt file2 ] file1比file2新
[ file1 -ot file2 ] file1比file2舊
文件檢驗:
[ -d $file ] or 表示判斷目錄是否存在
[[ -d $file ]]
[ -e $file ] or 表示判斷文件是否存在
[[ -e $file ]]
[ -f $file ] or 表示判斷非目錄普通文件是否存在
[[ -f $file ]]
[ -s $file ] or 表示判斷文件存在, 並且非0.
[[ -s $file ]]
[ -L $file ] or 表示判斷為鏈接符號存在
[[ -L $file ]]
[ -r $file ] or 表示判斷文件存在, 並且可讀.
[[ -r $file ]]
[ -w $file ] or 表示判斷文件存在, 並且可寫.
[[ -w $file ]]
[ -x $file ] or 表示判斷文件存在, 並且可執行.
[[ -x $file ]]
3) if語句:
if command //當command的返回狀態為0時執行then後面的語句.
then
command
fi
if test expr
then
command
fi
if [ string/numeric expr ]
then
command
fi
一下兩種為new format, 建議使用.
if [[ string expr ]] //支持通配符和擴展通配符(shopt -s extglob)
then
command
fi
if (( numeric expr ))
then
command
fi
if command
then
command1
else
command2
fi
if command
then
command1
elif command
then
command2
elif command
then
command3
else
command4
fi
4) 空語句:
用冒號表示.
if expr
then
:
fi
5) case語句: //;;相當於c語言中break.
case variable in
value1 | value2) // value1支持通配符和|作為or的關系
command1
;;
value3)
command2
;;
[vV]alue4)
command3
;;
*)
command4
;;
esac
6) 循環語句:
IFS 變量表示缺省的分隔符whitespace, tab, newline等. 可以自行修改該值, 但是建議再改之前賦值給其他變量作為備份, 有利於再恢復到缺省值.
for variable in word_list
do
commands
done
e.g.
for pal in Tom Dick Harry Joe
do
echo "Hi $pal"
done
echo "Out of loop"
for file in testfile[1-5]
do
if [[ -f $file ]]
then
echo "$file exist"
fi
done
for name in $* // 等同於 for name
do
echo "Hi $name"
done
while command //這裡當條件為true的時候, 或者command的退出為0時執行循環體的命令.
do
commands
done
while (( $num < 10 ))
do
echo -n "$num"
let num+=1
done
until !command //這裡當條件為false的時候, 或者command的退出為非0時執行循環體的命令.
do
commands
done
break/continue: 功能等同於c語言中的break和continue.
重定向循環和後台執行的循環:
while command
do
command
done > file //重定向到文件
while command
do
command
done | command //重定向到其他程序的管道
while command
do
command
done & //後台執行.
shift [n]命令: 用於把腳本的參數列表移出指定的位數, 不指定為左移一位, 一旦發生位移, 被移出的參數將永遠被刪除.
e.g.
[scriptname: doit]
while (( $# > 0 ))
do
echo $*
shift
done
/> doit a b c d e
a b c d e
b c d e
c d e
d e
e