高級shell腳本編程指南,【Linux】Linux腳本編程

 2023-10-05 阅读 29 评论 0

摘要:腳本編寫基礎 變量和參數 變量替換 變量的名字是它的值保存的地方。引用它的值稱為變量替換。如果varible1是一個變量,那么$varible1就是引用該變量的值,即這個變量包含的數據。 解釋:$為變量替換符,表示引用該變量的內容。 變量賦值 用“=”

腳本編寫基礎

變量和參數

變量替換

變量的名字是它的值保存的地方。引用它的值稱為變量替換。如果varible1是一個變量,那么$varible1就是引用該變量的值,即這個變量包含的數據。

解釋:$為變量替換符,表示引用該變量的內容。

變量賦值

用“=”對變量進行賦值,“=”的左右兩邊不能有空白符。

bash變量無類型

不同于許多其他編程語言,bash不以“類型”區分變量。本質上說,bash變量是字符串,但是根據環境的不同,bash允許變量有整數計算和比較操作,其中決定因素是變量的值是否只含有數字。比如:

#!/bin/sh
a="hello world"????????#對變量賦值
echo "A is:"????????????#打印變量
echo $a????????????????#打印變量a的內容

解釋:shell腳本的第一行必須以 #!/bin/sh 格式開頭,符號 #! 用來指定腳本文件的解析程序,當編譯好腳本后,如果要執行該腳本,還必須使其具有可執行的屬性。調用命令:

chmod +x shell腳本文件名

echo "內容"表示將文字內容打印到屏幕上。

有時變量名很容易與其他文字混淆,比如:

num=2
echo "this is the $numnd"

此時不會打印this is the 2nd的內容,而僅僅打印this is the,因為shell會去搜索變量numnd的值,但是這個變量是沒有值的。可以用花括號來告訴shell所要打印的是num變量,修改如下:

echo "this is the ${num}nd"

此時打印的內容就是this is the 2nd。

解析:{}花括號,這個結構表示代碼塊,也就是一組命令代碼塊,它是匿名的函數。與函數不同的是,在代碼塊里的變量仍然能被腳本后面的代碼訪問。

局部變量

局部變量只在代碼塊或者一個函數里有效。如果變量用local來聲明,那么它只能在該變量聲明的代碼塊中可見。這個代碼塊就是局部“范圍”。在一個函數內,局部變量意味著該變量只有在函數代碼塊內才有意義。比如:

#!/bin/bash
hello="var1"
echo $hello
function func1 {local hello="var2"echo $hello
}
func1
echo $hello

需要注意的是,function fun1 {...}其中fun1和大括號之間的空格不能省略,否則會出錯。

打開終端,建立該腳本文件,運行結果如下:

[root@localhost ~]# ./test1
var1
var2
var1

從結果就能看到局部變量的使用方法。

環境變量

環境變量會影響shell的行為和用戶接口,大多數情況下,每個進程都有一個環境表,它由一組被進程使用的環境變量組成。shell的其他進程也一樣,每次當一個shell啟動時,它都會創建新的合適的環境變量。

增加或更新一個環境變量,都會使這個shell的環境表得到更新,換句話說,更改或增加的變量會立即生效,并且這個shell的所有子進程(即它執行的命令)都能繼承它的環境變量。準確的說,是后繼生成的子進程才會繼承,已經運行的子進程并不會得到它的新環境變量。

分配給環境變量的總空間是有限的,如果創建太多的環境變量或者有的環境變量太長而占用太多的空間則會出錯。比如:

bash$ eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ'`"
bash$ du
bash:/usr/bin/du:Argument list too long(參數列表太長)

位置參數

位置參數是一種在調用Shell程序的命令行中按照各自的位置決定的變量,是在程序名之后輸入的參數,它們分別標識了用戶輸入的整個命令行中以空格分隔開的字符串。也就是說:位置參數就是通過命令行傳遞給腳本的參數(類似于C++中的cin>>的內容)。

位置參數的值可以用$N得到,N是一個整數(從0開始),Linux會把輸入的字符串分段(空格分段)并給每段進行編號,編號從0開始,第0號為程序名字,從1開始就表示傳遞給程序的參數。注意:在位置參數$9之后的參數必須要用括號括起來,例如:${10}、${11}等等。

位置參數的值總結
位置參數含義
$0當前這個Shell程序的文件名
$#?傳遞給程序的總的參數數目
$?上一個代碼或者Shell程序在Shell中退出的情況,如果正常退出則返回0,否則返回非0值
$*?傳遞給程序的所有參數組成的字符串
$n表示第n個參數(n<10)
$@以“參數1”、“參數2”……保存所有的參數
$$本程序的(進程ID)PID
$!?上一個命令的PID
${n}表示第n個參數(n>9)

例如:

#!/bin/bash
echo "number of vars:"$#
echo "values of vars:"$*
echo "value of var1:"$1
echo "value of var2:"$2
echo "value of var3:"$3
echo "value of var4:"$4

打開終端,建立該腳本文件,運行結果如下:

[root@localhost ~]# ./test1 1 2 3 4 5
number of vars:5
values of vars:1 2 3 4 5
value of var1:1
value of var2:2
value of var3:3
value of var4:4

退出和退出狀態

exit命令一般用于結束一個腳本,它也能返回一個值給父進程。每一個命令都能返回一個退出狀態(有時也看作返回狀態)。一個命令執行成功時返回0,執行不成功時則返回一個非零值(1-255),此值通常可以被解釋成一個對應的錯誤值。

同樣的,腳本里的函數和腳本本身都會返回一個退出狀態碼。在腳本會程序里被執行的最后一個命令將決定退出狀態碼。

如果一個腳本以不帶參數的exit命令結束,腳本的退出狀態碼將會是執行exit命令前的最后一個命令的退出碼。腳本結束沒有exit、不帶參數的exit和exit $?三者是等價的。

其中,$?變量保存了最后一個命令執行后的退出狀態。當一個函數返回時,$?保存了函數里最后一個命令的退出狀態碼,這就是bash里函數返回值的處理辦法。當一個腳本運行結束,$?變量保存腳本的退出狀態,而腳本的退出狀態就是腳本中最后一個已執行命令的退出狀態。

例如:

#!/bin/bash
echo "hello"
echo $?
lskdf
echo $?
exit 113

打開終端,建立該腳本文件,運行結果如下:

[root@localhost ~]# ./test1
hello
0
./test1:line4:lskdf:command not found
127

這里lskdf是無效命令,所以顯示錯誤原因。下一行echo $?,就打印前一個命令的退出狀態(127,非零)。

?

流程控制

對代碼塊的操作是構造和組織shell腳本的關鍵,循環和分支結構為腳本編程提供了操作代碼塊的工具,流程控制主要包括測試條件、循環控制語句、分支控制語句及與其相關的操作控制符。

條件測試

bash由test命令、各種括號和內嵌的操作符,以及if/then結構來完成條件測試的功能。通常用“[? ]”表示條件測試。注意,這里的空格很重要,要確保方括號兩側的空格。

比較操作符

比較操作包括整數比較操作、字符串比較操作和混合比較操作。常用的操作符如下表所示:

常用整數比較操作符
函數說明(例子)
-eq等于,if [ "$a" -eq "$b" ]
-ne不等于,if [ "$a" -ne "$b" ]
-gt大于,if [ "$a" -gt "$b" ]
-ge大于等于,if [ "$a" -ge "$b" ]
-lt小于,if [ "$a" -lt "$b" ]
-le小于等于,if [ "$a" -le "$b" ]
<小于(在雙括號內使用),(("$a"<"$b"))
<=小于等于(在雙括號內使用),(("$a"<="$b"))
>大于(在雙括號內使用),(("$a">"$b"))
>=大于等于(在雙括號內使用),(("$a">="$b"))
常用字符串比較操作符
函數說明(例子)
=等于,if [ "$a"="$b" ]
==等于,if [ "$a"=="$b" ],在[[? ]]結構里使用匹配模式
!=不等于,if [ "$a"!="$b" ],在[[? ]]結構里使用匹配模式
<小于,if [[ "$a"<"$b" ]],if [ "$a"\<"$b" ](在[]結構里<需要轉義)
>大于,if [[ "$a">"$b" ]],if [ "$a"\>"$b" ](在[]結構里>需要轉義)
-z字符串為“null”,長度為0
-n字符串不為“null”,長度不為0
常用混合比較操作符
函數說明
-a邏輯與
-o邏輯或

文件測試操作符

常用文件測試操作符
函數說明
-e文件存在
-f文件是一個普通文件(不是目錄或設備文件)
-s文件大小不為零
-d文件是一個目錄
-b文件是一個塊設備(如光盤、光驅)
-c文件是一個字符設備(如鍵盤、調制解調器、聲卡等)
-p文件是一個管道
-h文件是一個符號鏈接
-L文件是一個符號鏈接
-S文件是一個Socket
-t文件與一個終端設備相關
-r文件是否可讀
-w文件是否可寫
-x文件是否可執行
-g文件或目錄的sgid標志被設置
-u文件的sgid標志被設置

分析下列的測試目錄含義

[[ $a==z* ]]????????????????#如果變量$a以字符"z"開始(匹配模式)則為真
[[ $a=="z*" ]]????????????????#如果變量$a與字符"z*"(字面上的匹配)相等則為真
[ "$a"=="z*" ]????????????????#如果變量$a與字符"z*"(字面上的匹配)相等則為真
[ -f "somefile" ]????????????????#判斷是否為一個文件
[ -x "/bin/ls" ]????????????????#判斷/bin/ls是否有可執行的權限
[ -n "$var" ]????????????????#判斷$var變量是否有值
[ "$a"="$b" ]????????????????#判斷$a和$b是否相等

嵌套的if/then語句

if [ condition1 ]thenif [ condition2 ]thendo-something????????????#僅當condition1和condition2同時滿足才執行fi
fi

需要注意的是:

  • [ ]表示條件測試。注意這里的空格很重要。要注意在'['后面和']'前面都必須要有空格;
  • 在shell中,then和fi是分開的語句。如果要在同一行里面輸入,則需要用分號將他們隔開。

如果還有什么不理解的,可以參考鏈接:Shell腳本IF條件判斷和判斷條件總結。

操作符相關主題

常見的操作符主要包括賦值操作符、計算操作符、位操作符合邏輯操作符。它們與C語言的操作符是相同的。包括:

  • 賦值操作符:=;
  • 計算操作符:+、-、*、/、**(求冪)、%;
  • 位操作符:<<、<<=、>>、>>=、&、&=、|、|=、~、!、^、^=;
  • 邏輯運算符:&&、||。

循環控制

for循環

for arg in [list]
dodo-something
done

其中,list中的參數允許包括通配符。如果do和for想在同一行出現,那么在它們之間需要添加一個“;”。

while循環

while結構再循環的開始判斷條件是否滿足,如果條件一直滿足,那就一直循環下去(0為退出碼),與for循環的區別是,while結構適合在循環次數未知的情況下。while循環的結構如下:

while [condition]
dodo-something
done

和for循環一樣,如果想把do和條件放到同一行,需要一個“;”。

#!/bin/bash
var0=0
LIMIT=10
while [ "$var0" -lt "$LIMIT" ]
doecho -n "$var0"????????//-n將會阻止產生新行let "var0+=1"????????//let語句用于指定算術運算
done
exit 0

打開終端,建立該腳本文件,運行結果如下:

[root@localhost ~]# ./test1
0 1 2 3 4 5 6 7 8 9

until循環

until結構在循環的頂層判斷條件,如果條件一直為false,那就一直循環下去(與while相反)。until循環的結構如下:

until [condition-is-true]
dodo-something
done

和for循環一樣,如果想把do和條件放到同一行,需要一個“;”。

#!/bin/bash
END_CONDITION=end
until [ "$var1"="$END_CONDITION" ]
doecho "Input varible"echo "($END_CONDITION to exit)"read var1????????????????????????//提示用戶輸入,并將輸入值賦值給變量echo "varible=$var1"
done
exit()

打開終端,建立該腳本文件,運行結果如下:

[root@localhost ~]# ./test1
Input varible
(end to exit)
3
varible=3
Input varible
(end to exit)
end
varible=end

break和continue

break和continue這兩個循環控制命令與其他語言的類似命令的行為是相同的,break命令將會跳出循環,continue命令會跳過本次循環后面的語句,直接進入下次循環。

  • break命令可以帶一個參數,不帶參數的break循環只能退出最內層的循環,而break N則可以退出N層循環;
  • continue命令可以帶一個參數,不帶參數的continue命令只能跳過本次循環,而continue N則可以把N層循環剩余的代碼都跳過,但是循環的次數不變。

測試與分支

case和select結構在技術上不是循環,因為它們并不對可執行的代碼塊進行迭代。但是和循環相似的是,它們也依靠在代碼塊的頂部或底部的條件判斷來決定程序的分支。

shell中的case同C/C++中的switch結構是相同的,它允許通過條件來選擇執行代碼塊中多條路徑中的一條。它的作用和多個if/then/else語句相同,是它們的簡化結構,特別適合于創建目錄。

?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/122631.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息