? ? ? ? ? ? ? shell是一個(gè)用C語(yǔ)言編寫的應(yīng)用程序,它是一種命令語(yǔ)言又是一種程序設(shè)計(jì)語(yǔ)言禀苦。shell腳本(shell script)是一種為shell編寫的腳本程序,它與Windows下的批處理相似,用各類命令預(yù)先放入到一個(gè)文件中絮记,方便一次性執(zhí)行的一個(gè)程序文件,在Shell 中可以調(diào)用Linux 系統(tǒng)命令虐先。
? ? ? ? ? ? ? ? ? shell腳本和java編程一樣怨愤,只要有一個(gè)能編寫代碼的文本編輯器和一個(gè)能解釋執(zhí)行的腳本解釋器就可以了。
Linux的shell種類眾多蛹批,常見(jiàn)的有:
Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne? ?Again Shell(/bin/bash)
C? Shell(/bin/csh)等等
(常見(jiàn)的編程語(yǔ)言分為兩類:一個(gè)是編譯型語(yǔ)言撰洗,如java,運(yùn)行前要經(jīng)過(guò)編譯器的編譯腐芍;另一個(gè)是解釋型語(yǔ)言差导,執(zhí)行時(shí),需要使用解釋器一行一行的轉(zhuǎn)換為代碼猪勇,如:python设褐,shell)
第一個(gè)shell腳本
用vi或vim命令新建文件first.sh,擴(kuò)展名為sh(sh代表shell)埠对,擴(kuò)展名并不影響腳本執(zhí)行络断,見(jiàn)名知意即可
vim?first.sh
#!/bin/bash
echo“hello world!”
#!是一個(gè)約定的標(biāo)記,它告訴系統(tǒng)這個(gè)腳本需要什么解釋器來(lái)執(zhí)行项玛,即使用哪一種shell
echo命令用于向窗口輸出文本
執(zhí)行腳本有兩種方式:
一貌笨、? 作為可執(zhí)行程序執(zhí)行
1、? 首先要賦予腳本具有執(zhí)行權(quán)限
chmod u+x first.sh
2襟沮、? 輸入腳本的相對(duì)路徑或絕對(duì)路徑執(zhí)行腳本
./first.sh? #執(zhí)行腳本
或者從根目錄開(kāi)始用絕對(duì)路徑執(zhí)行腳本
二锥惋、 作為解釋器參數(shù)執(zhí)行
直接運(yùn)行解釋器,其參數(shù)就是shell腳本的文件名
sh? first.sh
以這種方式運(yùn)行的腳本开伏,不需要在第一行指定解釋器信息膀跌,寫了也沒(méi)用。
shell中的變量
linux中的變量分為系統(tǒng)變量和用戶自定義變量固灵,系統(tǒng)變量有:$PWD,$HOME,$USER等等捅伤,可以用set命令查看當(dāng)前shell中的所有變量(包括系統(tǒng)的和用戶自定義的)
定義變量:
語(yǔ)法:變量=值
變量命名只能使用英文字母,數(shù)字和下劃線巫玻,首字母不能以數(shù)字開(kāi)頭
變量名稱中間不能有空格丛忆,可以使用下劃線_
等號(hào)兩側(cè)不能有空格
變量名稱一般習(xí)慣大寫
不能使用標(biāo)點(diǎn)符號(hào)
不能使用bash里的關(guān)鍵字(可用help命令查看保留關(guān)鍵字)
使用變量:
只需要在一個(gè)定義過(guò)的變量前加美元符號(hào)$即可使用祠汇,如下:
使用readonly命令可以將變量定義為只讀變量,只讀變量的值
readonly? country=”china”
或
country=“china“
readonly? country
unset? A??? 撤銷變量A熄诡,unset命令不能刪除只讀變量
export? ?變量名??? 可以把變量提升為全局變量可很,可供其它shell程序使用
運(yùn)行shell時(shí),會(huì)同時(shí)存在三種變量:
1) 局部變量?局部變量在腳本或命令中定義凰浮,僅在當(dāng)前shell實(shí)例中有效我抠,其他shell啟動(dòng)的程序不能訪問(wèn)局部變量。
2) 環(huán)境變量?所有的程序袜茧,包括shell啟動(dòng)的程序菜拓,都能訪問(wèn)環(huán)境變量,有些程序需要環(huán)境變量來(lái)保證其正常運(yùn)行惫周。必要的時(shí)候shell腳本也可以定義環(huán)境變量尘惧。
3) shell變量?shell變量是由shell程序設(shè)置的特殊變量。shell變量中有一部分是環(huán)境變量递递,有一部分是局部變量喷橙,這些變量保證了shell的正常運(yùn)行
位置參數(shù)變量
$0? 當(dāng)前腳本的文件名
$n 傳遞給腳本或函數(shù)的參數(shù)。n為數(shù)字登舞,表示第幾個(gè)參數(shù)贰逾,$1-$9代表第一到第九個(gè)參數(shù),十以上的參數(shù)需要用大括號(hào)包含菠秒,如${10}
$* 傳遞給腳本或函數(shù)的所有參數(shù)
$@? 傳遞給腳本或函數(shù)的所有參數(shù)疙剑。
$# 傳遞給腳本或函數(shù)的參數(shù)個(gè)數(shù)
$* 和 $@ 的區(qū)別為:?$* 和 $@ 都表示傳遞給函數(shù)或腳本的所有參數(shù),不被雙引號(hào)("")包含時(shí)践叠,都以"$1" "$2" …"$n" 的形式輸出所有參數(shù)言缤。但是當(dāng)它們被雙引號(hào)(" ")包含時(shí),"$*" 會(huì)將所有的參數(shù)作為一個(gè)整體禁灼,以"$1 $2 …$n"的形式輸出所有參數(shù)管挟;"$@" 會(huì)將各個(gè)參數(shù)分開(kāi),以"$1""$2"… "$n" 的形式輸出所有參數(shù)
案例
打印輸入的參數(shù)總數(shù)弄捕,所有參數(shù)
預(yù)定義變量
$僻孝? (功能描述:最后一次執(zhí)行的命令的返回狀態(tài)。如果這個(gè)變量的值為0守谓,證明上一個(gè)命令正確執(zhí)行穿铆;如果這個(gè)變量的值為非0(具體是哪個(gè)數(shù),由命令自己來(lái)決定)斋荞,則證明上一個(gè)命令執(zhí)行不正確了荞雏。)
$$ (功能描述:當(dāng)前進(jìn)程的進(jìn)程號(hào)(PID))
$! (功能描述:后臺(tái)運(yùn)行的最后一個(gè)進(jìn)程的進(jìn)程號(hào)(PID))
變量替換
可以根據(jù)變量的狀態(tài)(是否為空,是否定義等)來(lái)改變它的值
命令替換:
把一個(gè)命令的輸出賦值給一個(gè)變量,方法為把命令用反引號(hào)(在Esc鍵下方)引起來(lái)
directory=`pwd`
echo $directory
運(yùn)算符
語(yǔ)法:1讯檐、$((運(yùn)算式))或$[運(yùn)算式]
????? 2羡疗、expr m + n???????????注意expr運(yùn)算符與表達(dá)式間要有空格,否則錯(cuò)誤
案例:計(jì)算(2+3)* 4的值
(1)采用$[運(yùn)算式]方式
S=$[(2+3)*4]
echo $S
(2) expr分布計(jì)算
S=`expr2 + 3`
expr? $S \* 4
#在expr中乘號(hào)為:\*
(3) expr一步完成計(jì)算
expr `expr 2 +3` \* 4
案例:
計(jì)算輸入的參數(shù) 1 和參數(shù) 2 的兩個(gè)數(shù)的和别洪,并輸出到控制臺(tái)
注意執(zhí)行腳本的時(shí)候后面帶參數(shù)
判斷語(yǔ)句
語(yǔ)法:[ 條件式 ]???
注意 條件式前后要有空格
非空返回true,可使用$?驗(yàn)證(0為true柳刮,>=1為false)
案例
按照文件權(quán)限進(jìn)行判斷
?? -r? 有讀的權(quán)限
?? -w? 有寫的權(quán)限
?? -x? 有執(zhí)行的權(quán)限
按照文件類型進(jìn)行判斷
? -f文件存在并且是一個(gè)常規(guī)的文件
? -e文件存在
? -d文件存在并是一個(gè)目錄
案例
算術(shù)運(yùn)算符
假定變量 a 為 10挖垛,變量 b 為20
在[ $a == $b ]與[ $a != $b ]中,需要在方括號(hào)與變量以及變量與運(yùn)算符之間有括號(hào)秉颗,否則為錯(cuò)誤的
關(guān)系運(yùn)算符
只支持?jǐn)?shù)字痢毒,不支持字符串
布爾運(yùn)算符
邏輯運(yùn)算符:
字符串運(yùn)算符:
文件測(cè)試運(yùn)算符
Shell中的字符串
字符串可以用單引號(hào)也可以用雙引號(hào)表示,區(qū)別如下:
單引號(hào)里的任何字符都會(huì)原樣輸出蚕甥,單引號(hào)字符串中的變量是無(wú)效的哪替;
單引號(hào)字符串中不能出現(xiàn)單獨(dú)一個(gè)的單引號(hào)(對(duì)單引號(hào)使用轉(zhuǎn)義符后也不行),但可以成對(duì)出現(xiàn)菇怀,作為字符串拼接使用
雙引號(hào)中可以有變量凭舶,可以出現(xiàn)轉(zhuǎn)義字符
拼接字符串:
獲取字符串的長(zhǎng)度:
str=”abcd”
echo ${#str}?? #輸出4
提取子字符串:
str=”hello world”
echo ${str:1:3}???#輸出ell
從字符串第2個(gè)字符開(kāi)始截取3個(gè)字符
查找子字符串:
查找字符i或s的位置(哪個(gè)字母先出現(xiàn)就計(jì)算哪個(gè))
str=”the sky is blue”
echo `expr index “$str” is`? #輸出5
Shell數(shù)組
bash支持一維數(shù)組,不支持多維數(shù)組爱沟,并且沒(méi)有限定數(shù)組大小帅霜,數(shù)組下標(biāo)由0開(kāi)始,利用下標(biāo)獲取數(shù)組元素
語(yǔ)法:數(shù)組名=(值1? 值2? 值3 …… 值n)
用括號(hào)表示數(shù)組呼伸,數(shù)組元素用空格分割開(kāi)
eg:array_name=(value1? value2?value3)
或array_name[0]=value1
array_name[1]=value2
array_name[2]=value3
array_name[n]=valuen
可以不使用連續(xù)的下標(biāo)身冀,而且下標(biāo)的范圍沒(méi)有限制
讀取數(shù)組:
讀取數(shù)組元素值的一般格式為:
${數(shù)組名[下標(biāo)]}?????????? eg:${array_name[0]}
使用@或*符號(hào)可以獲取數(shù)組中的所有元素??
eg:? echo? ${array_name[@]}或echo? ${array_name[*]}
獲取數(shù)組的信息:
獲取數(shù)組的長(zhǎng)度:
length=${#array_name[@]}或length=${#array_name[*]}
獲取數(shù)組的下標(biāo):
length=${!array_name[@]}或length=${!array_name[*]}
獲取數(shù)組單個(gè)元素的長(zhǎng)度
length1=${#array_name[1]}
Shell注釋
單行注釋前面加#即可
#這是一行注釋
多行注釋
1、? ? 可以用一對(duì)花括號(hào)將要注釋的代碼括起來(lái)括享,定義成函數(shù)搂根,沒(méi)有地方調(diào)用這個(gè)函數(shù),這塊代碼就不會(huì)執(zhí)行铃辖,達(dá)到和注釋一樣的效果
2剩愧、? ? 格式如下
:<<EOF
注釋內(nèi)容……
注釋內(nèi)容……
…………
注釋內(nèi)容……
EOF
其中EOF也可以使用其他符號(hào),如下:
:<<‘
注釋內(nèi)容……
注釋內(nèi)容……
‘
Shell中的echo命令:
echo命令用于字符串的輸出澳叉,語(yǔ)法:echo? string
可用echo實(shí)現(xiàn)更復(fù)雜的輸出格式控制
1隙咸、顯示普通字符串
echo “It is a test”或echo? it is a test??(這里雙引號(hào)可省略,效果一樣)
2成洗、顯示轉(zhuǎn)義字符
echo? “\“the skyis blue\””???? #輸出為”the sky is blue”
echo中可以用于的轉(zhuǎn)義符有:
轉(zhuǎn)義字符????含義
\\? ? ? ? ? ? ? ? 反斜杠
\a? ? ? ? ? ? ? ?警報(bào)五督,響鈴
\b? ? ? ? ? ? ? ?退格(刪除鍵)
\c? ? ? ? ? ? ? ?不換行
\f????????????????換頁(yè)(FF),將當(dāng)前位置移到下頁(yè)開(kāi)頭
\n????????????????換行
\r????????????????回車
\t????????????????水平制表符(tab鍵)
\v????????????????垂直制表符
使用echo命令的-E選項(xiàng)禁止轉(zhuǎn)義瓶殃,使用-n選項(xiàng)可以禁止插入換行符充包,使用-e選項(xiàng)可以進(jìn)行轉(zhuǎn)義
3、 顯示結(jié)果定向至文件
echo? “hello? world” >>hello.txt
意為將hello? world輸入到hello.txt文件中
4、? ?顯示命令執(zhí)行結(jié)果
echo? `date`
注意:這里使用的是反引號(hào)基矮,而不是單引號(hào)淆储,結(jié)果將顯示當(dāng)前系統(tǒng)日期
Shell中的流程控制
if判斷
基本語(yǔ)法:([ 條件判斷式 ] if 和中括號(hào)和條件判斷式之間必須有空格)
1、if? [? 條件判斷式? ];then
?????????????? #程序
??? fi
或者if? [? 條件判斷式? ]
????? then???? #程序
???? fi
2家浇、if [ 條件判斷式]
then?? #程序
else?
????? #程序
fi
3本砰、? ?if [條件判斷式]
????????then?? #程序
????? elif [條件判斷式]
????????then?? #程序
????? else
??????????? #程序
????? fi
?案例
case語(yǔ)句
基本語(yǔ)法:
case $變量名in
"值1")
#如果變量的值等于值1,則執(zhí)行程序1
;;
"值2")
#如果變量的值等于值2钢悲,則執(zhí)行程序2
;;
…省略其他分支…
*)
#如果變量的值都不是以上的值点额,則執(zhí)行此程序
;;
esac
取值后面必須為單詞in,每一模式必須以右括號(hào)結(jié)束莺琳。取值可以為變量或常數(shù)还棱。匹配發(fā)現(xiàn)取值符合某一模式后,其間所有命令開(kāi)始執(zhí)行直至 ;;取值將檢測(cè)匹配的每一個(gè)模式惭等。一旦模式匹配珍手,則執(zhí)行完匹配模式相應(yīng)命令后不再繼續(xù)其他模式。如果無(wú)一匹配模式辞做,使用星號(hào) * 捕獲該值琳要,再執(zhí)行后面的命令
案例:
for循環(huán)
基本語(yǔ)法:
1、 for 變量in 值1?值2?值3…
? ? ? do
? ? ? ? ? ? ? ?#程序
? ? ? ?done
注意:列表是一組值(數(shù)字凭豪、字符串等)組成的序列焙蹭,每個(gè)值通過(guò)空格分隔。每循環(huán)一次嫂伞,就將列表中的下一個(gè)值賦給變量
當(dāng)變量值在列表里孔厉,for循環(huán)即執(zhí)行一次所有命令,使用變量名獲取列表中的當(dāng)前取值帖努。命令可為任何有效的shell命令和語(yǔ)句撰豺。in列表可以包含替換、字符串和文件名拼余。in列表是可選的污桦,如果不用它,for循環(huán)使用命令行的位置參數(shù)匙监。
2凡橱、? ?for((初始值;循環(huán)控制條件;變量變化))
? ? ? ? ? ? ?do
? ? ? ? ? ? ? ? ? ? ? ? #程序
? ? ? ? ? ? done
案例
while循環(huán)
基本語(yǔ)法:
while?[?條件判斷式?]
?do
? ? ? ? ? ? ?#程序
done
或
while((條件表達(dá)式))
? ? ?do
? ? ? ? ? ? ? #程序
? ? ?done
案例
until循環(huán)
until循環(huán)執(zhí)行一系列命令直至條件為 true 時(shí)停止,與 while 循環(huán)在處理方式上剛好相反亭姥。???
基本語(yǔ)法:
until?condition
do
?? command
done
condition一般為條件表達(dá)式稼钩,如果返回值為 false,則繼續(xù)執(zhí)行循環(huán)體內(nèi)的語(yǔ)句达罗,否則跳出循環(huán)坝撑。?
shell中的break和continue
shell也支持break和continue静秆,和其他編程語(yǔ)言用法一樣,在循環(huán)中可使用 break 與continue 跳出循環(huán)巡李,另外抚笔,break 命令后面還可以跟一個(gè)整數(shù),表示跳出第幾層循環(huán)侨拦。
read讀取控制臺(tái)輸入
基本語(yǔ)法:
read(選項(xiàng))(參數(shù))
選項(xiàng)
-p:指定讀取值時(shí)的提示符殊橙;
-t:指定讀取值時(shí)等待的時(shí)間(秒)。
參數(shù)
變量:指定讀取值的變量名
函數(shù)
系統(tǒng)函數(shù)
1狱从、? basename基本語(yǔ)法
basename [pathname] [suffix]
basename [string] [suffix]
(功能描述:basename命令會(huì)刪掉所有的前綴包括最后一個(gè)(‘/’)字符蛀柴,然后將字符串顯示出來(lái)。
選項(xiàng)
suffix 為后綴矫夯,如果suffix 被指定了,basename 會(huì)將pathname 或string 中的suffix 去掉
?basename?/home/yin/1.txt????????? -> 1.txt
?basename??/home/yin/1.txt????.txt?????? -> 1
2吊洼、? dirname基本語(yǔ)法
dirname? 文件絕對(duì)路徑??
從給定的包含絕對(duì)路徑的文件名中去除文件名(非目錄的部分)训貌,然后返回剩下的路徑(目錄的部分)
dirname /usr/bin/????????? -> /usr
dirname stdio.h??????????? -> .
自定義函數(shù)
基本語(yǔ)法(function關(guān)鍵字可加可不加)
function 函數(shù)名()
{
??? #程序
}
調(diào)用函數(shù):函數(shù)名 參數(shù)1 參數(shù)2 ……
注意:
在函數(shù)體內(nèi)部,通過(guò)$n的形式來(lái)獲取參數(shù)的值冒窍,如$1表示第一個(gè)參數(shù)递沪,$2表示第二個(gè)參數(shù)……
必須在調(diào)用函數(shù)地方之前,先聲明函數(shù)综液,shell腳本是逐行運(yùn)行款慨。不會(huì)像其它語(yǔ)言一樣先編譯。
shell函數(shù)返回值只能是整數(shù)谬莹,一般用來(lái)表示函數(shù)執(zhí)行成功與否檩奠,0表示成功,其它值表示失敗附帽,只能通過(guò)$?系統(tǒng)變量獲得埠戳,可以顯示加:return返回,如果不加蕉扮, 將以最后一條命令運(yùn)行結(jié)果整胃,作為返回值。return后跟數(shù)值n(0-255)
刪除函數(shù)也可以使用unset命令喳钟,不過(guò)要加上.f選項(xiàng)
unset? .f? function_name