linux下的shell腳本(基本)
先說(shuō)明以下內(nèi)容來(lái)自: http://c.biancheng.net/cpp/shell/ 库北,C語(yǔ)言中文網(wǎng)廉羔,請(qǐng)大家支持原作,點(diǎn)擊鏈接查看荆永。
Shell是一種腳本語(yǔ)言朝捆,那么般渡,就必須有解釋器來(lái)執(zhí)行這些腳本,常見(jiàn)的腳本解釋器有:
bash:是Linux標(biāo)準(zhǔn)默認(rèn)的shell芙盘。bash由Brian Fox和Chet Ramey共同完成驯用,是BourneAgain Shell的縮寫(xiě),內(nèi)部命令一共有40個(gè)儒老。
sh: 由Steve Bourne開(kāi)發(fā)晨汹,是Bourne Shell的縮寫(xiě),sh 是Unix 標(biāo)準(zhǔn)默認(rèn)的shell贷盲。
另外還有:ash淘这、 csh、 ksh等巩剖。
常見(jiàn)的編程語(yǔ)言分為兩類(lèi):一個(gè)是編譯型語(yǔ)言铝穷,如:c/c++/java等,它們遠(yuǎn)行前全部一起要經(jīng)過(guò)編譯器的編譯佳魔。另一個(gè)解釋型語(yǔ)言曙聂,執(zhí)行時(shí),需要使用解釋器一行一行地轉(zhuǎn)換為代碼鞠鲜,如:awk, perl, python與shell等宁脊。
Shell 經(jīng)過(guò)了POSIX的標(biāo)準(zhǔn)化,所以它是可以在不同的linux系統(tǒng)上進(jìn)行移植贤姆。
關(guān)于注釋的問(wèn)題: 在shell中使用#進(jìn)行注釋?zhuān)⒁庥馨瑂h里面沒(méi)有多行注釋?zhuān)荒苊恳恍屑右粋€(gè)#號(hào);
第一個(gè)shell腳本程序:
#!/bin/bash
# 上面中的 #! 是一種約定標(biāo)記, 它可以告訴系統(tǒng)這個(gè)腳本需要什么樣的解釋器來(lái)執(zhí)行; echo "Hello, world!"
變量:
定義變量:
country="China" Number=100
注意: 1,變量名和等號(hào)之間不能有空格;
2,首個(gè)字符必須為字母(a-z霞捡,A-Z)坐漏。
3, 中間不能有空格,可以使用下劃線(xiàn)(_)。
4, 不能使用標(biāo)點(diǎn)符號(hào)赊琳。
5, 不能使用bash里的關(guān)鍵字(可用help命令查看保留關(guān)鍵字)街夭。
使用變量:
只需要在一個(gè)定義過(guò)的變量前面加上美元符號(hào) $ 就可以了, 另外,對(duì)于變量的{} 是可以選擇的, 它的目的為幫助解釋器識(shí)別變量的邊界.
country="China"
echo $country echo ${country} echo "I love my ${country}abcd!"
#這個(gè)需要有{}的;
**重定義變量:** 直接把變量重新像開(kāi)始定義的那樣子賦值就可以了:
country="China" country="ribenguizi"
**只讀變量**: 用 readonly 命令 可以把變量字義為只讀變量躏筏。
readonly country="China" #或
country="China" readonly country
刪除變量: 使用unset命令可以刪除變量板丽,但是不能刪除只讀的變量。用法:
unset variable_name
變量類(lèi)型
運(yùn)行shell時(shí)趁尼,會(huì)同時(shí)存在三種變量:
1) 局部變量
局部變量在腳本或命令中定義埃碱,僅在當(dāng)前shell實(shí)例中有效,其他shell啟動(dòng)的程序不能訪(fǎng)問(wèn)局部變量弱卡。
2) 環(huán)境變量
所有的程序,包括shell啟動(dòng)的程序住册,都能訪(fǎ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)行
特殊變量:
$* 和 $@ 的區(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ù)。
$? 可以獲取上一個(gè)命令的退出狀態(tài)店印。所謂退出狀態(tài)冈在,就是上一個(gè)命令執(zhí)行后的返回結(jié)果。退出狀態(tài)是一個(gè)數(shù)字按摘,一般情況下包券,大部分命令執(zhí)行成功會(huì)返回 0,失敗返回 1炫贤。
Shell中的替換
轉(zhuǎn)義符:
在echo中可以用于的轉(zhuǎn)義符有:
使用 echo 命令的 –e 選項(xiàng)可以對(duì)轉(zhuǎn)義字符進(jìn)行替換溅固。
另外,注意兰珍,經(jīng)過(guò)我的實(shí)驗(yàn)发魄,得到:
echo "\\" #得到 \
echo -e "\\" #得到 \
echo "\\\\" #得到 \\
echo -e "\\" #得到 \
命令替換:
它的意思就是說(shuō)我們把一個(gè)命令的輸出賦值給一個(gè)變量,方法為把命令用反引號(hào)(在Esc下方)引起來(lái). 比如:
directory=
pwd
echo $directory
變量替換:
可以根據(jù)變量的狀態(tài)(是否為空、是否定義等)來(lái)改變它的值.
Shell運(yùn)算符
算數(shù)運(yùn)算符:
原生bash不支持簡(jiǎn)單的數(shù)學(xué)運(yùn)算,但是可以通過(guò)其他命令來(lái)實(shí)現(xiàn)励幼,例如 awk 和 expr. 下面使用expr進(jìn)行汰寓; expr是一款表達(dá)式計(jì)算工具,使用它可以完成表達(dá)式的求值操作苹粟;
比如:
a=10 b=20
expr $a + $b
expr $a - $b
expr $a \* $b
expr $a / $b
expr $a % $b
a=$b
注意: 1\. 在expr中的乖號(hào)為:\*
2\. 在 expr中的 表達(dá)式與運(yùn)算符之間要有空格有滑,否則錯(cuò)誤;
3\. 在[ $a == $b ]與[ $a != $b ]中嵌削,要需要在方括號(hào)與變量以及變量與運(yùn)算符之間也需要有括號(hào)毛好, 否則為錯(cuò)誤的。(親測(cè)過(guò))
關(guān)系運(yùn)算符:
只支持?jǐn)?shù)字苛秕,不支持字符串肌访,除非字符串的值是數(shù)字。常見(jiàn)的有:
注意:也別忘記了空格艇劫;
布爾運(yùn)算符:
字符串運(yùn)算符:
文件測(cè)試運(yùn)算符:
檢測(cè) Unix 文件的各種屬性吼驶。
Shell中的字符串
單引號(hào)的限制:
- 單引號(hào)里的任何字符都會(huì)原樣輸出,單引號(hào)字符串中的變量是無(wú)效的店煞;
- 單引號(hào)字串中不能出現(xiàn)單引號(hào)(對(duì)單引號(hào)使用轉(zhuǎn)義符后也不行)蟹演。
雙引號(hào)的優(yōu)點(diǎn):
- 雙引號(hào)里可以有變量
- 雙引號(hào)里可以出現(xiàn)轉(zhuǎn)義字符
#### 拼接字符串:
country="China"
echo "hello, $country" #也可以 echo "hello, "$country" "
#### 獲取字符串長(zhǎng)度:
string="abcd"
echo ${#string} #輸出 4
#### 提取子字符串:
string="alibaba is a great company"
echo ${string:1:4} #輸出liba
**查找子字符串:**
string="alibaba is a great company"
echo `expr index "$string" is`
#### 處理路經(jīng)的字符串:
例如:當(dāng)一個(gè)路徑為 /home/xiaoming/1.txt時(shí),如何怎么它的路徑(不帶文件) 和如何得到它的文件名顷蟀?酒请?
得到文件名使用 bashname命令:
# 參數(shù):
# -a,表示處理多個(gè)路徑;
# -s, 用于去掉指定的文件的后綴名鸣个; basename /home/yin/1.txt - 1.txt
basename -a /home/yin/1.txt /home/zhai/2.sh -
1.txt 2.sh basename -s .txt /home/yin/1.txt - 1
basename /home/yin/1.txt .txt - 1
得到路徑名(不帶文件名)使用 dirname命令:
參數(shù):沒(méi)有啥參數(shù)羞反; //例子:
dirname /usr/bin/ - /usr dirname dir1/str dir2/str -
dir1
dir2
dirname stdio.h - .
Shell的數(shù)組:
bash支持一維數(shù)組, 不支持多維數(shù)組, 它的下標(biāo)從0開(kāi)始編號(hào). 用下標(biāo)[n] 獲取數(shù)組元素;
**定義數(shù)組:**
在shell中用括號(hào)表示數(shù)組囤萤,元素用空格分開(kāi)苟弛。 如:
array_name=(value0 value1 value2 value3)
也可以單獨(dú)定義數(shù)組的各個(gè)分量,可以不使用連續(xù)的下標(biāo)阁将,而且下標(biāo)的范圍沒(méi)有限制膏秫。如:
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
**讀取數(shù)組:**
讀取某個(gè)下標(biāo)的元素一般格式為:
${array_name[index]}
讀取數(shù)組的全部元素,用@或*
${array_name[*]}
${array_name[@]}
**獲取數(shù)組的信息:**
取得數(shù)組元素的個(gè)數(shù):
length=${#array_name[@]}
#或
length=${#array_name[*]}
獲取數(shù)組的下標(biāo):
length=${!array_name[@]}
#或
length=${!array_name[*]}
取得數(shù)組單個(gè)元素的長(zhǎng)度:
lengthn=${#array_name[n]}
### printf函數(shù):
它與c語(yǔ)言中的printf相似做盅,不過(guò)也有不同缤削,下面列出它的不同的地方:
1. printf 命令不用加括號(hào)
2. format-string 可以沒(méi)有引號(hào),但最好加上吹榴,單引號(hào)雙引號(hào)均可亭敢。
3. 參數(shù)多于格式控制符(%)時(shí),format-string 可以重用图筹,可以將所有參數(shù)都轉(zhuǎn)換帅刀。
4. arguments 使用空格分隔让腹,不用逗號(hào)。
下面為例子:
# format-string為雙引號(hào)
$ printf "%d %s\n" 1 "abc"
1 abc
# 單引號(hào)與雙引號(hào)效果一樣
$ printf '%d %s\n' 1 "abc"
1 abc
# 沒(méi)有引號(hào)也可以輸出
$ printf %s abcdef
abcdef
# 格式只指定了一個(gè)參數(shù)扣溺,但多出的參數(shù)仍然會(huì)按照該格式輸出骇窍,format-string 被重用
$ printf %s abc def
abcdef
$ printf "%s\n" abc def
abc
def
$ printf "%s %s %s\n" a b c d e f g h i j
a b c
d e f
g h i
j
# 如果沒(méi)有 arguments,那么 %s 用NULL代替锥余,%d 用 0 代替
$ printf "%s and %d \n" and 0 # 如果以 %d 的格式來(lái)顯示字符串腹纳,那么會(huì)有警告,提示無(wú)效的數(shù)字驱犹,此時(shí)默認(rèn)置為 0 $ printf "The first program always prints'%s,%d\n'" Hello Shell -bash: printf: Shell: invalid number
The first program always prints 'Hello,0' $
### Shell中條件語(yǔ)句
#### if 語(yǔ)句
包括:1嘲恍, if [ 表達(dá)式 ] then 語(yǔ)句 fi
2\. if [ 表達(dá)式 ] then 語(yǔ)句 else 語(yǔ)句 fi
3. if [ 表達(dá)式] then 語(yǔ)句 elif[ 表達(dá)式 ] then 語(yǔ)句 elif[ 表達(dá)式 ] then 語(yǔ)句 …… fi
例子:
a=10 b=20
if [ $a == $b ] then
echo "a is equal to b"
else
echo "a is not equal to b"
fi
另外:if ... else 語(yǔ)句也可以寫(xiě)成一行,以命令的方式來(lái)運(yùn)行雄驹,像這樣:
if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;
其中佃牛,test 命令用于檢查某個(gè)條件是否成立,與方括號(hào)([ ])類(lèi)似医舆。
**case …… esac語(yǔ)句**
case ... esac 與其他語(yǔ)言中的 switch ... case 語(yǔ)句類(lèi)似俘侠,是一種多分枝選擇結(jié)構(gòu)。case語(yǔ)句格式如下:
case 值 in 模式1)
command1
command2
command3
;;
模式2)
command1
command2
command3
;; *)
command1
command2
command3
;; esac
其中彬向, 1\. 取值后面必須為關(guān)鍵字 in兼贡,每一模式必須以右括號(hào)結(jié)束攻冷。取值可以為變量或常數(shù)娃胆。匹配發(fā)現(xiàn)取值符合某一模式后,其間所有命令開(kāi)始執(zhí)行直至 ;;等曼。;; 與其他語(yǔ)言中的 break 類(lèi)似里烦,意思是跳到整個(gè) case 語(yǔ)句的最后。2\. 如果無(wú)一匹配模式禁谦,使用星號(hào) * 捕獲該值胁黑,再執(zhí)行后面的命令。
### Shell 的循環(huán)語(yǔ)句
**for 循環(huán) **
一般格式為:
for 變量 in 列表 do command1
command2
...
commandN done
注意:列表是一組值(數(shù)字州泊、字符串等)組成的序列丧蘸,每個(gè)值通過(guò)空格分隔。每循環(huán)一次遥皂,就將列表中的下一個(gè)值賦給變量力喷。 例如:
順序輸出當(dāng)前列表的數(shù)字:
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
顯示主目錄下以 .bash 開(kāi)頭的文件:
#!/bin/bash for FILE in $HOME/.bash*
do
echo $FILE done
**while循環(huán)**
**一般格式為:**
while command do Statement(s) to be executed if command is true
done
例如:
COUNTER=0
while [ $COUNTER -lt 5 ] do COUNTER='expr $COUNTER+1'
echo $COUNTER done
**until 循環(huán)**
until 循環(huán)執(zhí)行一系列命令直至條件為 true 時(shí)停止。until 循環(huán)與 while 循環(huán)在處理方式上剛好相反演训。 常用格式為:
until command do Statement(s) to be executed until command is true
done
command 一般為條件表達(dá)式弟孟,如果返回值為 false,則繼續(xù)執(zhí)行循環(huán)體內(nèi)的語(yǔ)句样悟,否則跳出循環(huán)拂募。
類(lèi)似地庭猩, 在循環(huán)中使用 break 與continue 跳出循環(huán)。 另外陈症,break 命令后面還可以跟一個(gè)整數(shù)蔼水,表示跳出第幾層循環(huán)。
Shell函數(shù)
Shell函數(shù)必須先定義后使用爬凑,定義如下徙缴,
function_name () {
list of commands
[ return value ]
}
也可以加上function關(guān)鍵字:
function function_name () {
list of commands
[ return value ]
}
注意:1\. 調(diào)用函數(shù)只需要給出函數(shù)名,不需要加括號(hào)嘁信。
2\. 函數(shù)返回值于样,可以顯式增加return語(yǔ)句;如果不加潘靖,會(huì)將最后一條命令運(yùn)行結(jié)果作為返回值穿剖。
3\. Shell 函數(shù)返回值只能是整數(shù),一般用來(lái)表示函數(shù)執(zhí)行成功與否卦溢,0表示成功糊余,其他值表示失敗。
4\. 函數(shù)的參數(shù)可以通過(guò) $n 得到.如:
funWithParam(){ echo "The value of the first parameter is $1 !"
echo "The value of the second parameter is $2 !"
echo "The value of the tenth parameter is ${10} !"
echo "The value of the eleventh parameter is ${11} !"
echo "The amount of the parameters is $# !" # 參數(shù)個(gè)數(shù) echo "The string of the parameters is $* !" # 傳遞給函數(shù)的所有參數(shù)
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
5\. 像刪除變量一樣单寂,刪除函數(shù)也可以使用 unset 命令贬芥,不過(guò)要加上 .f 選項(xiàng),如下所示:
unset .f function_name
### shell的文件包含:
Shell 也可以包含外部腳本宣决,將外部腳本的內(nèi)容合并到當(dāng)前腳本蘸劈。使用:
. filename
#或
source filename
1\. 兩種方式的效果相同,簡(jiǎn)單起見(jiàn)尊沸,一般使用點(diǎn)號(hào)(.)威沫,但是注意點(diǎn)號(hào)(.)和文件名中間有一空格。
2\. 被包含腳本不需要有執(zhí)行權(quán)限洼专。