目 錄
1、 Shell簡介
1.1. 什么是shell
1.2. shell分類
2、 Shell語法
2.1. 定義變量
2.2. 變量類型
2.2.1. 字符集變量
2.2.2. 數(shù)字常量定義
2.2.3. 數(shù)組
2.2.4. 系統(tǒng)變量
2.3. 運(yùn)算符與表達(dá)式
2.3.1. 運(yùn)算符
2.3.2. 字符串表達(dá)式(判斷條件命令if)
2.3.3. 字符串操作
2.3.4. 數(shù)值表達(dá)式
2.3.5. 復(fù)合條件表達(dá)式
2.4. 流程控制
2.4.1. 條件轉(zhuǎn)移 :if 條件語句
2.4.2. 選擇語句case
2.4.3. 循環(huán)語句
2.5. Shell中的函數(shù)運(yùn)用
2.5.1. 函數(shù)聲明
2.5.2. 局部變量
2.5.3. Shell腳本文件的參數(shù)
2.5.4. 函數(shù)的參數(shù)
2.6. 類型變量
2.6.1. declare 聲明類型變量
2.7. Shell文件中的交互功能
2.8. 轉(zhuǎn)義(\)
Linux Shell學(xué)習(xí)筆記
Linux系統(tǒng)的shell作為操作系統(tǒng)的外殼,為用戶提供使用操作系統(tǒng)的接口。它是命令語言、命令解釋程序及程序設(shè)計(jì)語言的統(tǒng)稱。
shell是用戶和Linux內(nèi)核之間的接口程序,如果把Linux內(nèi)核想象成一個球體的中心,shell就是圍繞內(nèi)核的外層。當(dāng)從shell或其他程序向Linux傳遞命令時(shí),內(nèi)核會做出相應(yīng)的反應(yīng)。
shell是一個命令語言解釋器,它擁有自己內(nèi)建的shell命令集,shell也能被系統(tǒng)中其他應(yīng)用程序所調(diào)用。用戶在提示符下輸入的命令都由shell先解釋然后傳給Linux核心。
有一些命令,比如改變工作目錄命令cd,是包含在shell內(nèi)部的。還有一些命令,例如拷貝命令cp和移動命令rm,是存在于文件系統(tǒng)中某個目錄下的單獨(dú)的程序。對用戶而言,不必關(guān)心一個命令是建立在shell內(nèi)部還是一個單獨(dú)的程序。
shell首先檢查命令是否是內(nèi)部命令,若不是再檢查是否是一個應(yīng)用程序(這里的應(yīng)用程序可以是Linux本身的實(shí)用程序,如ls和rm,也可以是購買的商業(yè)程序,如xv,或者是自由軟件,如emacs)。然后shell在搜索路徑里尋找這些應(yīng)用程序(搜索路徑就是一個能找到可執(zhí)行程序的目錄列表)。如果鍵入的命令不是一個內(nèi)部命令并且在路徑里沒有找到這個可執(zhí)行文件,將會顯示一條錯誤信息。如果能夠成功找到命令,該內(nèi)部命令或應(yīng)用程序?qū)⒈环纸鉃橄到y(tǒng)調(diào)用并傳給Linux內(nèi)核。
shell的另一個重要特性是它自身就是一個解釋型的程序設(shè)計(jì)語言,shell程序設(shè)計(jì)語言支持絕大多數(shù)在高級語言中能見到的程序元素,如函數(shù)、變量、數(shù)組和程序控制結(jié)構(gòu)。shell編程語言簡單易學(xué),任何在提示符中能鍵入的命令都能放到一個可執(zhí)行的shell程序中。
當(dāng)普通用戶成功登錄,系統(tǒng)將執(zhí)行一個稱為shell的程序。正是shell進(jìn)程提供了命令行提示符。作為默認(rèn)值(TurboLinux系統(tǒng)默認(rèn)的shell是BASH),對普通用戶用“$”作提示符,對超級用戶(root)用“#”作提示符。
一旦出現(xiàn)了shell提示符,就可以鍵入命令名稱及命令所需要的參數(shù)。shell將執(zhí)行這些命令。如果一條命令花費(fèi)了很長的時(shí)間來運(yùn)行,或者在屏幕上產(chǎn)生了大量的輸出,可以從鍵盤上按ctrl+c發(fā)出中斷信號來中斷它(在正常結(jié)束之前,中止它的執(zhí)行)。
當(dāng)用戶準(zhǔn)備結(jié)束登錄對話進(jìn)程時(shí),可以鍵入logout命令、exit命令或文件結(jié)束符(EOF)(按ctrl+d實(shí)現(xiàn)),結(jié)束登錄。
Linux中的shell有多種類型,其中最常用的幾種是Bourne shell(sh)、C shell(csh)和Korn shell(ksh)。三種shell各有優(yōu)缺點(diǎn)。Bourne shell是UNIX最初使用的shell,并且在每種UNIX上都可以使用。Bourne shell在shell編程方面相當(dāng)優(yōu)秀,但在處理與用戶的交互方面做得不如其他幾種shell。Linux操作系統(tǒng)缺省的shell是Bourne Again shell,它是Bourne shell的擴(kuò)展,簡稱Bash,與Bourne shell完全向后兼容,并且在Bourne shell的基礎(chǔ)上增加、增強(qiáng)了很多特性。Bash放在/bin/bash中,它有許多特色,可以提供如命令補(bǔ)全、命令編輯和命令歷史表等功能,它還包含了很多C shell和Korn shell中的優(yōu)點(diǎn),有靈活和強(qiáng)大的編程接口,同時(shí)又有很友好的用戶界面。
C shell是一種比Bourne shell更適于編程的shell,它的語法與C語言很相似。 Linux為喜歡使用C shell的人提供了Tcsh。Tcsh是C shell的一個擴(kuò)展版本。Tcsh包括命令行編輯、可編程單詞補(bǔ)全、拼寫校正、歷史命令替換、作業(yè)控制和類似C語言的語法,它不僅和Bash shell是提示符兼容,而且還提供比Bash shell更多的提示符參數(shù)。
Korn shell集合了C shell和Bourne shell的優(yōu)點(diǎn)并且和Bourne shell完全兼容。Linux系統(tǒng)提供了pdksh(ksh的擴(kuò)展),它支持任務(wù)控制,可以在命令行上掛起、后臺執(zhí)行、喚醒或終止程序。
shell語言是非類型的解釋型語言,不象用C++/JAVA語言編程時(shí)需要事先聲明變量.給一個變量賦值,實(shí)際上就是定義了變量.
由于shell程序的變量是無類型的,所以用戶可以使用同一個變量時(shí)而存放字符時(shí)而存放數(shù)字。
在linux支持的所有shell中,都可以用賦值符號(=)為變量賦值.
如:
abc=9 (bash/pdksh不能在等號兩側(cè)留下空格 )
如:
name=abc (bash/pdksh)
在變量賦值之后,只需在變量前面加一個$去引用.
如:
echo $abc
字符集變量的聲明方法是用雙引號
如:
abc=”how are you ” (將字符集 how are you 賦值給abc)
echo $abc
輸出結(jié)果:how are you
引用系統(tǒng)變量賦值
如:
abc=”$LOGNAME,how are you”; ($LOGNAME 存儲了系統(tǒng)登錄用戶名)
echo $abc
輸出結(jié)果:root,how are you
字符串相加
abc=” how are you”” root”
echo $abc
輸出結(jié)果:how are you root
十進(jìn)制:直接寫數(shù)字
如:a=12 #a是十進(jìn)制12
八進(jìn)制:在前面加0
如:a=012 #a是八進(jìn)制12
十六禁止:在數(shù)字前加0x
如:a=0x12 #a是十六進(jìn)制12
數(shù)組下標(biāo)是以零為開始;
數(shù)組的使用方法
如:
arr1=(1 2 3 4 5) # 定義數(shù)組arr1,并初始化5個值
echo ${arr1[0]} #打印數(shù)組中第零個變量值
arr1[0]=6 #將數(shù)組中第0個值賦值為6
echo ${arr1[0]} #打印數(shù)組中第零個變量值
系統(tǒng)變量就是環(huán)境變量,系統(tǒng)變量定義后可以直接在操作系統(tǒng)中調(diào)用,對于不同的用戶,其所有的系統(tǒng)變量也不同;
系統(tǒng)變量用export聲明,如:
export varname=”system var” #聲明varname 為系統(tǒng)變量;
可以在操作系統(tǒng)提示符下直接訪問varname
如:#echo $varname
執(zhí)行結(jié)果:system var
算術(shù)運(yùn)算符
+ 加法
- 減法
* 乘法
/ 除法
** 冪運(yùn)算
let "z=5**3"
echo "z = $z" # z = 125
% 取模
+= 加等于(通過常量增加變量)
如:let "var += 5" #var將在本身值的基礎(chǔ)上增加5
-= 減等于
*= 乘等于
如:let "var *= 4"
/= 除等于
%= 取模賦值,
算術(shù)操作經(jīng)常使用expr或者let表達(dá)式
邏輯運(yùn)算符
|| 邏輯或
&& 邏輯與
Str1 = str2 當(dāng)str1與str2相同時(shí),返回True
Str1! = str2 當(dāng)str1與str2不同時(shí),返回True
Str 當(dāng)str不是空字符時(shí),返回True
-n str 當(dāng)str的長度大于0時(shí),返回True
-z str 當(dāng)str的長度是0時(shí),返回True
例如:文件b.sh如下
#!/bin/bash
A1="abc"
B1="abc"
C1="abcde"
if [ "$A1" = "$B1" ]
then
echo "A1=B1"
fi
if [ "$A1" != "$C1" ]
then
echo "A1<>C1"
fi
if [ -n "$A1" ]
then
echo "$A1 length>0"
fi
輸出結(jié)果:
A1=B1
A1<>C1
abc length>0
得到字符串長度,使用方法:expr length para
#para代表字符串變量
截取字符串,使用方法:${para:X1:X2}
#para代表字符串變量參數(shù),X1代表截取位置,X2代表截取長度,可省略
子串刪除,使用方法:{string#substring}
#從string中刪除第一個子串substring;
子串替換,
${string/substring/replacement}
使用$replacement來替換第一個匹配的$substring.
${string//substring/replacement}
使用$replacement來替換所有匹配的$substring.
如文件b.sh
#!/bin/bash
string1=teststring
expr length $string1 #字符串長度
echo ${string1:0} #輸出字符串
echo ${string1:1} #輸出子字符串,從第二個字符開始到字符串結(jié)尾
echo ${string1:1:3} #輸出第1至3個字符
echo ${string1#test} #刪除字符串中的test子串
echo ${string1/test/replace} #將字符串中的子串test替換為replace
輸出結(jié)果:
10
teststring
eststring
est
string
- 判斷語句
Int1 -eq int2 #當(dāng)int1等于int2時(shí),返回True
Int1 -ge int2 #當(dāng)int1大于/等于int2時(shí),返回True
Int1 -le int2 #當(dāng)int1小于/等于int2時(shí),返回True
Int1 -gt int2 #|當(dāng)int1大于int2時(shí),返回True
Int1 -ne int2 #當(dāng)int1不等于int2時(shí),返回True
實(shí)例:如下文件 b.sh
#!/bin/bash
int1=3
int2=4
if [ $int1 -eq $int2 ]
then
echo "int1=int2"
else
echo "int1<>int2"
fi
執(zhí)行結(jié)果:
Int1<>int2
實(shí)例:如文件b.sh
#!/bin/bash
int1=3
int2=4
if [ $int1 -ge 1 ] && [ $int2 -le 7 ]
then
echo "int1>=1 and int2<=7"
fi
if [ $int1 -ge 1 ] || [ $int2 -le 1 ]
then
echo "int1>=1 or int2<=1"
fi
執(zhí)行結(jié)果:
int1>=1 and int2<=7
int1>=1 or int2<=1
語法:
if [ 條件 ]
then #符合條件
表達(dá)式
else #不符合條件
表達(dá)式
fi #結(jié)束條件
詳細(xì)例子在本文檔中各實(shí)例中均有介紹
- 選擇比較運(yùn)算符,從下面的條件中選擇出一個復(fù)合條件的表達(dá)式
如文件:b.sh
#!/bin/bash
a1=2;
case $a1 in
1)
echo "a1=1";;
2)
echo "a1=2";;
esac
執(zhí)行結(jié)果:a1=2
- 以下列出三種常用的循環(huán)語句的用法,三種程序?qū)崿F(xiàn)相同功能
- For 循環(huán)
|
- While循環(huán)
|
- Until循環(huán)
|
實(shí)例:b.sh #!/bin/bash for i in 1 2 3 4 5 do echo “$i” done&
|
實(shí)例:b.sh #!/bin/bash i=1 while [$i –le 5] do let “ i += 1 ” echo “$i” done |
實(shí)例:b.sh #!/bin/bash i=0 until [ $i -eq 5 ] do let " i += 1 " echo "$i" done |
- 輸出結(jié)果
1 2 3 4 5 |
- 輸出結(jié)果
1 2 3 4 5 |
- 輸出結(jié)果
1 2 3 4 5 |
Shell中的函數(shù)運(yùn)用
函數(shù)聲明:
Function_name() #聲明函數(shù)
{
command #函數(shù)的主體,執(zhí)行的命令;
}
例如:b.sh
#!/bin/bash
testfunction() #函數(shù)聲明和處理過程
{
echo "this is a test function"
}
testfunction #函數(shù)調(diào)用
執(zhí)行結(jié)果:this is a test function
函數(shù)中的局部變量用local聲明,變量的作用范圍是本函數(shù)內(nèi)部,函數(shù)執(zhí)行完畢后局部變量被刪除;
如下實(shí)例b.sh
#!/bin/bash
abc=112233 #聲明全局變量abc
localpara() #定義函數(shù)
{
local abc=123 #定義局部變量abc,注意區(qū)分上面的abc
echo "local para abc is $abc" #輸出局部變量
}
localpara #調(diào)用函數(shù),輸出局部變量abc
echo "abc is $abc" #輸出全局變量abc,變量值沒有改變
執(zhí)行結(jié)果:
local para abc is 123
abc is 112233
Shell腳本文件的參數(shù)
文件參數(shù)
在shell腳本中使用參數(shù)的方法如下:
./b.sh start #start 就是第一個參數(shù)
調(diào)用方法:
./b.sh test1 輸出結(jié)果是:this is runpara1
./b.sh test2 輸出結(jié)果是:this is runpara2
特殊的文件參數(shù)
$0 腳本程序名稱
$n 程序文件的第n個參數(shù)
$* 程序文件的所有參數(shù)
$# 程序文件參數(shù)的個數(shù)
$$ 程序文件執(zhí)行時(shí)的PID
看如下腳本文件b.sh
#!/bin/bash
runpara1() #函數(shù)聲明
{
echo "this is runpara1"
}
runpara2() ##函數(shù)聲明
{
echo "this is runpara2"
}
if [ $# -gt 0 ]
then
echo “para count >0”
fi
case $1 in # $1 代表第一個參數(shù)的值
test1) #如果參數(shù)是test1就執(zhí)行函數(shù)runpara1
runpara1
;;
test2)
runpara2
;;
esac
如下文件 b.sh
#!/bin/bash
testfunction () #聲明函數(shù)
{
if [ -z "$1" ] #判斷函數(shù)是否存在參數(shù)($1)
then
echo "no para in function" #無參數(shù)處理過程
else
echo "function's paraname is "$1"" #有參數(shù)處理過程
fi
}
testfunction start #執(zhí)行函數(shù),函數(shù)的參數(shù)是start
執(zhí)行結(jié)果:function’s paraname is start
declare –r abc=”test string” #聲明abc是只讀類型
declare –i int1 #聲明int1是整數(shù)類型
declare –a arr1 #聲明arr1為數(shù)組變量
declare -f 函數(shù)名(可選) #當(dāng)存在函數(shù)名時(shí),只會列出文件中的名稱是所寫函數(shù)的定義,如果不存在函數(shù)名,則列出所有函數(shù)的聲明
看下面的例子b.sh:
#!/bin/bash
declare -r abc="test declare" #聲明只讀變量abc
echo "echo $abc"
abc="read only" #將會出現(xiàn)錯誤提示,因?yàn)閍bc是只讀變量
echo "echo $abc" #打印abc變量,還是“test declare”沒有變化
declare -i int1 #聲明整型變量int1
int1=12;
int1="test string" #給整型賦值為字符串,錯誤
echo "$int1"
int1=int1/3 #整型變量可以直接使用操作符/
echo “$int1”
func1() #聲明函數(shù)func1
{
echo "test function"
}
func2() #聲明函數(shù)func2
{
echo "test function"
}
declare –f #顯示所有函數(shù)
declare -f func1 #顯示函數(shù)func1
文件的執(zhí)行結(jié)果如下:
echo test declare
./b.sh: abc: readonly variable #只讀變量錯誤提示
echo test declare
./b.sh: test string: syntax error in expression (error token is "string") #變量類型錯誤
12
4 #顯示的是 12/3的結(jié)果
declare -f func1 () #顯示所有函數(shù)
{
echo "test function"
}
declare -f func2 ()
{
echo "test function"
}
func1 () #顯示函數(shù)func1
{
echo "test function"
}
程序需要對用戶輸入的字符進(jìn)行判斷后執(zhí)行相應(yīng)的操作
如下面的文件b.sh
#程序完成的功能是,判斷用戶輸入的名稱,如果用戶輸入的名稱不是zhangwei,就繼續(xù)提示輸入,如果用戶輸入了zhangwei,就提示歡迎字符,程序退出;
#!/bin/bash
while :
do
echo -n "please input you name:" #提示用戶輸入
read line #讀取用戶輸入的數(shù)據(jù)
if [ "$line" = "zhangwei" ] #判斷用戶輸入的數(shù)據(jù)
then
echo "welcome $line" #顯示歡迎信息
exit
fi
done
轉(zhuǎn)義是一種引用單個字符的方法.一個具有特殊含義的字符前邊放上一個轉(zhuǎn)義符(\)就告訴shell這個字符失去了特殊的含義.
對于特定的轉(zhuǎn)義符的特殊的含義(在echo和sed中所使用)
\n 換行
\r 回車
\t tab鍵
\v vertical tab(垂直tab),查前邊的Ctl-K
\b backspace,查前邊的Ctl-H
\a "alert"(如beep或flash)
\0xx 轉(zhuǎn)換成8進(jìn)制ASCII解碼,等價(jià)于oxx
實(shí)例,使用轉(zhuǎn)義符“\”
看下文件b.sh
#!/bin/bash
echo "\v\v\v\v" # 打印字符串”\v\v\v\v .”
echo -e "\v\v\v\v" #打印4個垂直tab
echo $’\v\v\v\v’ #打印4個垂直tab
echo –e “\101” #打印出A,因?yàn)锳是101的八進(jìn)制的ascII
echo \z #輸出 z
echo '\z' #輸出 \z
echo \\z #輸出 \z