SHELL

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)的限制:

  1. 單引號(hào)里的任何字符都會(huì)原樣輸出,單引號(hào)字符串中的變量是無(wú)效的店煞;
  2. 單引號(hào)字串中不能出現(xiàn)單引號(hào)(對(duì)單引號(hào)使用轉(zhuǎn)義符后也不行)蟹演。

雙引號(hào)的優(yōu)點(diǎn):

  1. 雙引號(hào)里可以有變量
  2. 雙引號(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)限洼专。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棒掠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屁商,更是在濱河造成了極大的恐慌烟很,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜡镶,死亡現(xiàn)場(chǎng)離奇詭異雾袱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)帽哑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén)谜酒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妻枕,你說(shuō)我怎么就攤上這事僻族≌吵郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵述么,是天一觀的道長(zhǎng)蝌数。 經(jīng)常有香客問(wèn)我,道長(zhǎng)度秘,這世上最難降的妖魔是什么顶伞? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮剑梳,結(jié)果婚禮上唆貌,老公的妹妹穿的比我還像新娘。我一直安慰自己垢乙,他們只是感情好锨咙,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著追逮,像睡著了一般酪刀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钮孵,一...
    開(kāi)封第一講書(shū)人閱讀 52,895評(píng)論 1 314
  • 那天骂倘,我揣著相機(jī)與錄音,去河邊找鬼巴席。 笑死历涝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的情妖。 我是一名探鬼主播睬关,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诱担,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼毡证!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蔫仙,我...
    開(kāi)封第一講書(shū)人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤料睛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后摇邦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體恤煞,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年施籍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了居扒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丑慎,死狀恐怖喜喂,靈堂內(nèi)的尸體忽然破棺而出瓤摧,到底是詐尸還是另有隱情,我是刑警寧澤玉吁,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布照弥,位于F島的核電站,受9級(jí)特大地震影響进副,放射性物質(zhì)發(fā)生泄漏这揣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一影斑、第九天 我趴在偏房一處隱蔽的房頂上張望给赞。 院中可真熱鬧,春花似錦矫户、人聲如沸塞俱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)障涯。三九已至,卻和暖如春膳汪,著一層夾襖步出監(jiān)牢的瞬間唯蝶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工遗嗽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粘我,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓痹换,卻偏偏與公主長(zhǎng)得像征字,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娇豫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容