1. 程式人生 > >Linux Shell程式設計基礎入門

Linux Shell程式設計基礎入門

shell指令碼通常以#!/bin/bash 起始

指令碼的執行方式有兩種。

  1. 將指令碼名作為命令列引數: bash myScript.sh

  2. 授予指令碼執行許可權,將其變為可執行檔案: chmod 755 myScript.sh ./myScript.sh

終端中顯示輸出

$ echo "Welcome to Bash" 
Welcome to Bash 

雙引號允許shell解釋字串中出現的特殊字元。單引號不會對其做任何解釋

echo -e 接受雙包含轉義序列的雙引號字串作為引數

echo -e "1\t2\t3" 
1  2  3

文字顏色是由對應的色彩碼來描述的。其中包括:重置=0,黑色=30,紅色=31,綠色=32, 黃色=33,藍色=34,洋紅=35,青色=36,白色=37
要列印彩色文字,可輸入如下命令:

echo -e "\e[1;31m This is red text \e[0m" 

彩色背景,經常使用的顏色碼是:重置=0,黑色=40,紅色=41,綠色=42,黃色=43, 藍色=44,洋紅=45,青色=46,白色=47
要設定彩色背景的話,可輸入如下命令:

echo -e "\e[1;42m Green Background \e[0m"

變數與環境變數

var="value"   
# 將"value"
賦給變數var echo $var

envprintenv命令檢視當前shell 中所定義的全部環境變數

在PATH中新增一條新路徑,可以使用如下命令:

export PATH="$PATH:/home/user/bin" 

另外還有一些眾所周知的環境變數:HOMEPWDUSERUIDSHELL

獲得字串的長度

$ var=12345678901234567890 
$ echo ${#var} 
20 

識別當前所使用的shell echo $SHELLecho $0
檢查是否為超級使用者

If [ $UID -ne 0 ]; then   
	echo Non root user.
Please run as root. else echo Root user fi

操作符[]

result=$[ no1 + no2 ] 

[]中可以使用$字首

result=$[ $no1 + 5 ] 

檔案描述符與重定向

檔案描述符是與某個開啟的檔案或資料流相關聯的整數。檔案描述符0、 1以及2是系統預留的

  • 0 —— stdin (標準輸入)
  • 1 —— stdout(標準輸出)
  • 2 —— stderr(標準錯誤)

使用大於號將文字儲存到檔案中 $ echo "This is a sample text 1" > temp.txt
使用雙大於號將文字追加到檔案中 $ echo "This is sample text 2" >> temp.txt
使用2>(數字2以及大於號)將stderr重定向到out.txt $ ls + 2> out.txt

有一種方法既可以將資料重定向到檔案,還可以提供一份重定向資料的副本作為管道中後續命令的stdin。tee命令從stdin中讀取,然後將輸入資料重定向到stdout以及一個或多個檔案中

command | tee FILE1 FILE2 | otherCommand 

$ cat a* | tee out.txt | cat -n 

重定向指令碼內部的文字塊

#!/bin/bash 
cat<<EOF>log.txt 
This is a generated file. Do not edit. Changes will be overwritten. 
EOF

出現在cat <<EOF>log.txt與下一個EOF行之間的所有文字行都會被當作stdin資料。 log.txt檔案的內容顯示如下:

$ cat log.txt 
This is a generated file. Do not edit. Changes will be overwritten. 

陣列與關聯陣列

在單行中使用數值列表來定義一個數組

array_var=(test1 test2 test3 test4 test5 test6) #這些值將會儲存在以0為起始索引的連續位置上 

打印出特定索引的陣列元素內容

echo ${array_var[0]} 
test1 
index=5 
echo ${array_var[$index]} 
test6 

以列表形式打印出陣列中的所有值

$ echo ${array_var[*]} 
test1 test2 test3 test4 test5 test6 

列印陣列長度(即陣列中元素的個數):

$ echo ${#array_var[*]}
6 

關聯陣列中,我們可以用任意的文字作為陣列索引。首先,需要使用宣告語句將一個變數 定義為關聯陣列:

$ declare -A fruits_value 
$ fruits_value=([apple]='100 dollars' [orange]='150 dollars') 

顯示陣列內容:

$ echo "Apple costs ${fruits_value[apple]}" 
Apple costs 100 dollars

列出陣列索引

$ echo ${!fruits_value[*]} 
orange apple 

別名

建立別名

$ alias new_command='command sequence' 

下面的命令為apt-get install建立了一個別名:

$ alias install='sudo apt-get install' 

alias命令的效果只是暫時的。一旦關閉當前終端,所有設定過的別名就失效了。為了 使別名在所有的shell中都可用,可以將其定義放入~/.bashrc檔案中

$ echo 'alias cmd="command seq"' >> ~/.bashrc 

如果需要刪除別名,只需將其對應的定義(如果有的話)從~/.bashrc中刪除,或者使用 unalias命令。也可以使用alias example=,這會取消別名example

採集終端資訊

tput命令的功能演示
獲取終端的行數和列數:

tput cols 
tput lines

打印出當前的終端名:

 tput longname

將游標移動到座標(100,100)處:

tput cup 100 100 

設定終端背景色:

tput setb n 
#其中,n可以在07之間取值。 

設定終端前景色:

tput setf n
# 其中,n可以在07之間取值。 

設定文字樣式為粗體:

tput bold

設定下劃線的起止:

tput smul tput rmul 

刪除從當前游標位置到行尾的所有內容:

tput ed 

輸入密碼時,指令碼不應該顯示輸入內容。在下面的例子中,我們將看到如何使用stty來 實現這一需求

#!/bin/sh 
#Filename: password.sh 
echo -e "Enter password: " 
# 在讀取密碼前禁止回顯 
stty -echo 
read password 
# 重新允許回顯 
stty echo 
echo 
echo Password read. 

stty命令的選項-echo禁止將輸出傳送到終端,而選項echo則允許傳送輸出。

除錯指令碼

使用選項-x,啟用shell指令碼的跟蹤除錯功能:

$ bash -x script.sh 

使用set -xset +x對指令碼進行部分除錯

#!/bin/bash 
#檔名: debug.sh 
for i in {1..6}; 
do     
	set -x     
	echo $i     
	set +x 
done 
echo "Script executed" 

在上面的指令碼中,只會打印出echo $i的除錯資訊,因為使用-x和+x對除錯區域進行 了限制。

set -x:在執行時顯示引數和命令。
set +x:禁止除錯。
set -v:當命令進行讀取時顯示輸入。
set +v:禁止列印輸入。

把第一行從#!/bin/bash改成 #!/bin/bash -xv,這樣一來,不用任何其他選項就可以 啟用除錯功能了

函式和引數

  • $0是指令碼名稱。
  • $1是第一個引數。
  • $2是第二個引數。
  • $n是第n個引數。
  • [email protected]“被擴充套件成”$1” “$2” "$3"等。
  • $*“被擴充套件成”$1c$2c$3”,其中c是IFS的第一個字元。
  • "[email protected]“要比”$*“用得多。由於”$*"將所有的引數當作單個字串,因此它很少被使用。

函式和別名乍一看很相似,不過兩者在行為上還是略有不同。大的差異在於函式引數可以 在函式體中任意位置上使用,而別名只能將引數放在命令尾部。

如果想獲得/sbin/ifconfig檔案中裝置對應的IP地址,可以嘗試這樣做:

$> alias wontWork='/sbin/ifconfig | grep' 
$> wontWork eth0 
eth0  Link  encap:Ethernet  HWaddr 00:11::22::33::44:55 

如果我們使用函式來實現的話,可以將 裝置名作為引數傳入ifconfig,不再交給grep

$> function getIP() { /sbin/ifconfig $1 | grep 'inet '; } 
$> getIP eth0 
inet addr:192.168.1.2 Bcast:192.168.255.255 Mask:255.255.0.0 

shift命令可以將引數依次向左移動一個位 置,讓指令碼能夠使用$1來訪問到每一個引數

$ cat showArgs.sh 
for i in `seq 1 $#` 
do 
	echo $i is $1 
	shift 
done 
$ sh showArgs.sh a b c 
1 is a 
2 is b 
3 is c

讀入 n個字元

從輸入中讀取n個字元並存入變數variable_name:

read -n number_of_chars variable_name 

用無回顯的方式讀取密碼:

read -s var 

使用read顯示提示資訊:

read -p "Enter input:"  var 

在給定時限內讀取輸入:

read -t timeout var 

例如:

$ read -t 2 var 
#在2秒內將鍵入的字串讀入變數var 

用特定的定界符作為輸入行的結束:

read -d delim_char var 

例如:

$ read -d ":" var 
hello: #var被設定為hello

比較與測試

們可以用if、 if else以及邏輯運算子來測試

[ condition ] && action; # 如果condition為真,則執行action
[ condition ] || action; # 如果condition為假,則執行action

算術比較
[ $var -eq 0 ] #當$var等於0時,返回真
[ $var -ne 0 ] #當$var不為0時,返回真
● -gt:大於。
● -lt:小於。
● -ge:大於或等於。
● -le:小於或等於
-a是邏輯與操作符,-o是邏輯或操作符

檔案系統相關測試
● [ -f $file_var ]:如果給定的變數包含正常的檔案路徑或檔名,則返回真。
● [ -x $var ]:如果給定的變數包含的檔案可執行,則返回真。
● [ -d $var ]:如果給定的變數包含的是目錄,則返回真。
● [ -e $var ]:如果給定的變數包含的檔案存在,則返回真。
● [ -c $var ]:如果給定的變數包含的是一個字元裝置檔案的路徑,則返回真。
● [ -b $var ]:如果給定的變數包含的是一個塊裝置檔案的路徑,則返回真。
● [ -w $var ]:如果給定的變數包含的檔案可寫,則返回真。
● [ -r $var ]:如果給定的變數包含的檔案可讀,則返回真。
● [ -L $var ]:如果給定的變數包含的是一個符號連結,則返回真。

字串比較
● [[ -z $str1 ]]:如果str1為空串,則返回真。
● [[ -n $str1 ]]:如果str1不為空串,則返回真。