Linux Shell程式設計基礎入門
shell指令碼通常以#!/bin/bash
起始
指令碼的執行方式有兩種。
-
將指令碼名作為命令列引數:
bash myScript.sh
-
授予指令碼執行許可權,將其變為可執行檔案:
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
用env
或printenv
命令檢視當前shell 中所定義的全部環境變數
在PATH中新增一條新路徑,可以使用如下命令:
export PATH="$PATH:/home/user/bin"
另外還有一些眾所周知的環境變數:HOME
、PWD
、USER
、UID
、SHELL
等
獲得字串的長度
$ var=12345678901234567890
$ echo ${#var}
20
識別當前所使用的shell echo $SHELL
、 echo $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可以在0到7之間取值。
設定終端前景色:
tput setf n
# 其中,n可以在0到7之間取值。
設定文字樣式為粗體:
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 -x
和set +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不為空串,則返回真。