語法結構
賦值語句 : var=value
變量解析 : ${var}
命令解析 : ${command}
雙引號 " " : 變量內容,並做轉義
單引號 ' ' : 變量內容,但不做轉義
反單引號 ` ` : 同 $()
alexis@Smilodon:~$ version=v1.0 alexis@Smilodon:~$ echo $version v1.0 alexis@Smilodon:~$ v2="$(uname) abc ${version}" alexis@Smilodon:~$ echo $v2 Linux abc v1.0 alexis@Smilodon:~$ echo "$LANG" en_US.UTF-8 alexis@Smilodon:~$ echo '$LANG' $LANG alexis@Smilodon:~$ echo `uname -r` 3.2.0-33-generic-pae
export與子進程:
如果需要在子進程(在一個shell中打開另一個shell)中使用父進程的變量,則需要使用export將自定義變量轉為環境變量
alexis@Smilodon:~$ name=alexis alexis@Smilodon:~$ echo $name alexis alexis@Smilodon:~$ bash alexis@Smilodon:~$ echo $name alexis@Smilodon:~$ exit alexis@Smilodon:~$ export name alexis@Smilodon:~$ bash ealexis@Smilodon:~$ echo $name alexis alexis@Smilodon:~$ exit
unset: 取消變量
alexis@Smilodon:~$ name=liu alexis@Smilodon:~$ echo $name liu alexis@Smilodon:~$ unset name alexis@Smilodon:~$ echo $name
幾個重要的環境變量
$OSTYPE: 操作系統類型
$HOSTTYPE: 主機默認安裝的軟件主要類型,32位的有 i386, i586, i686, 64位為 x86_64
$MACHTYPE: 安裝的機器類型
$$: 當前shell的PID
$?: 上一個命令的返回值,如果上一個命令執行成功則返回0
read, array, declare
read: 讀取用戶輸入到某個變量
alexis@Smilodon:~$ read -p "Please enter your name: " name Please enter your name: Alexis alexis@Smilodon:~$ echo $name Alexis
屏幕會輸出 Please enter your name: 並等待用戶輸入,最后將輸入賦值到name
array: bash數組的賦值與輸出
alexis@Smilodon:~$ arr[0]=1 alexis@Smilodon:~$ arr[1]=2 alexis@Smilodon:~$ arr[2]=3 alexis@Smilodon:~$ echo ${arr} 1 alexis@Smilodon:~$ echo ${arr[1]} 2 alexis@Smilodon:~$ echo ${arr[2]} 3
declare: 聲明變量類型
declare -x name: 將 name 變成環境變量
declare +x name: 將 name 恢復成自定義變量
declare -i product=10*10: 將product定義成整形,這樣后面的表達式就會得到計算
alexis@Smilodon:~$ declare -i product=10*10 alexis@Smilodon:~$ echo $product 100
declare -r name: 將 name 定義成只讀變量
declare -a product: 將 product 定義成數組類型
declare -p product: 查看 product 的類型信息
變量微調
1) 變量內容的刪除
alexis@Smilodon:~$ path=${PATH} alexis@Smilodon:~$ echo ${path} /usr/local/glassfish3/jdk7/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games alexis@Smilodon:~$ echo ${path#/*bin:} /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games alexis@Smilodon:~$ echo ${path} /usr/local/glassfish3/jdk7/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games alexis@Smilodon:~$ echo ${path##/*bin:} /usr/games
${path#/*bin:}
path: 需要微調的變量名
#: 從左邊開始刪除所匹配的最短的字符串,類似與正則里的非貪婪匹配
##: 表示從左邊開始刪除匹配的最長的字符串,類似與正則的貪婪匹配
/*bin: : 表示以 / 開頭, *是通配符表示任意個任意字符, 以 bin: 結尾的字符串
注意執行這個表達式以后原來的path並不會被修改,我們只是將修改后的值輸出了而已
如果要從右邊開始匹配則用 % , %% 替換 #, ##
2) 變量內容的替換
var=${str-val}: 當變量str未設置,則 var=val, 若變量str已經設置,則var=str
var=${str:-val}: 當變量str未設置或者為空串, 則var=val
var=${str+val}: 當變量str已經設置, 則var=val,否則var=空串
var=${str:+val}: 當變量str已經設置且非空串,則var=val,否則var=空串
var=${str=val}: 若str已經設置,則var=val,str不變,若str未設置,則var=str=val
var=${str:=val}: 若str已經設置且非空,則var=val,str不變,若str未設置或為空串,則var=str=val
var=${str?val}: 若str未設置,則輸出str到stderr,若str已經設置,則var=str
var=${str:?val}: 若str為設置或者為空串,則輸出str到stderr,若str已經設置切非空,則var=str
bash的登錄與歡迎信息
/etc/issue 文件: 記錄了bash登錄前的歡迎信息,相關信息可以用 man issue 查看
/etc/motd 文件: 記錄了bash登錄成功后的歡迎信息
bash的環境配置文件
login shell: 在輸入帳號密碼登錄的時候取得的bash,例如從tty1-tty6登錄
non-login shell: 取得bash不需要完整的登錄流程,例如在圖形界面開啟Terminal
Login Shell讀取配置文件流程
而非登錄shell僅僅會讀取 ~/.bashrc
通配符(wildcard)
*: 代表任意個任意字符
?: 代表1個任意字符
[abc]: 代表a或b或c中的一個
[a-z]: 代表 a~z這個范圍
[^abc] : 代表除了a或b或c以外的字符
數據流重定向:
0: STDIN 標准輸入
1: STDOUT 標准輸出
2: STDERR 標准錯誤輸出
>, >>: 輸出流重定向, > 為 覆蓋,>> 為追加
cat infile 1> outfile 2>&1
將 2 重定向到 1, 再將 1 重定向到 outfile 文件,意思是將標准錯誤輸出和標准輸出都存入outfile
find /home 2> /dev/null
將錯誤輸出 /dev/null, /dev/null是垃圾黑洞,可以將信息忽略
< : 輸入重定向
cat > catfile < ~/test
用 test 文件的內容代替STDIN輸入到 catfile里
<<: eof符號
cat > catfile << 'eof'
你可以使用STDIN(鍵盤輸入)來輸入到catfile,當輸入eof時,輸入結束,相當於點了 ctrl + d
命令執行依據 ; && ||
; : 順序執行
&& : 且 邏輯, cmdA && cmdB, 只有cmdA成功了才會繼續執行cmdB,成功的依據就是 $? 這個狀態回傳碼
|| : 或邏輯, cmdA || cmdB 只有cmdA執行失敗才會繼續執行cmdB
管道(pipe | )
管道可以將前一個命令的stdout當作后一個命令的stdin,只有特定的管道命令才能使用
管道命令有 cut,grep,sort,wc,uniq,tee,tr,col,join,paste,expand等
而ls cd這些命令則不是管道命令,如果需要使用管道則需要用xargs作參數代換
- 號的用途
- 號可以代替 STDOUT STDIN
tar -czv -f - /home | tar -xzv -f -
第一個 - 代替stdout,第二個 - 代替stdin,想當於用tar來實現cp
算數運算
$((a*b)) : 計算a與b的乘積,只支持整數
source命令
source命令用於運行shell腳本,它與bash/sh或者直接以路徑運行腳本的區別在於,source是在父進程中運行,而bash是在子進程中運行,在子進程中產生的變量在父進程中將不可見,所以在運行系統配置腳本的時候應該使用source
$# 與 $@
$0 : 腳本名稱
$1 , $2 , $3 ... : 參數 1 2 3 ...
$# : 腳本參數個數
$@ : 腳本所有參數名
if ... elif ... then ... fi 條件判斷語句
#!/bin/bash # 使用 if then else fi 獲取端口狀態 testing=$(netstat -tualn | grep ":80") if [ "$testing" != "" ]; then echo "WWW port 80 is running in your system" fi testing=$(netstat -tualn | grep ":21") if [ "$testing" != "" ]; then echo "FTP port 21 is running in your system" fi testing=$(netstat -tualn | grep ":22") if [ "$testing" != "" ]; then echo "SSH port 22 is running in your system" fi testing=$(netstat -tualn | grep ":25") if [ "$testing" != "" ]; then echo "MAIL port 25 is running in your system" fi
case ... esac 選擇語句
#!/bin/bash #test case ... esac echo "Exit system?" echo "1.yes 2.no" read -p "Enter your choice: " choice case $choice in "1") echo "Exit now" ;; "2") echo "Not exit" ;; *) echo "Plase enter 1 or 2" ;; esac
function函數
#!/bin/bash #use function() function printit() { echo "$0 Printing $1" } printit "myparam"
while 循環
#!/bin/bash # test while loop while [ "$yn" != "yes" -a "$yn" != "no" ] do read -p "Please input yes/no: " yn done echo "Good!" i=0 s=0 while [ "$i" -lt 100 ] do i=$(($i+1)) s=$(($s+$i)) done echo "The sum is $s"
for的用法
1.使用 for ... in ... do ... done
#!/bin/bash # test for ... in ... do ... done # 查看子網是否聯通 ip="192.168.1" for sitenu in $(seq 1 100) do ping -c 1 -w 1 "${ip}.${sitenu}" &> /dev/null && result=1 || result=0 if [ "$result" == 1 ]; then echo "${ip}.${sitenu} is ON" else echo "${ip}.${sitenu} is DOWN" fi done
#!/bin/bash #查看目錄下所有文件權限 read -p "Enter a directory: " dir if [ "$dir" == "" -o ! -d "$dir" ]; then echo "The $dir is NOT exist in your system." exit 1 fi filelist=$(ls $dir) for filename in $filelist do perm="" test -r "$dir/$filename" & perm="$perm readable" test -w "$dir/$filename" & perm="$perm writable" test -x "$dir/$filename" & perm="$perm executable" echo "The file $filename's permission is $perm" done
2. 使用 for (()) 語法
#!/bin/bash # test for if [ $# != 1 ]; then echo "Usage $0 {maxnum}" exit 1; fi s=0 for (( i=1; i<=$1; i++ )) do s=$(($s+$i)) done echo "The sum of 1+2+3..+$1 is $s"
1 #!/bin/bash #表明該腳本使用sh或bash 2 #This is a sample 3 4 #usage of variable 5 year=1999; #變量賦值語句 6 7 #usage of expression 8 year=`expr $year + 1`; #變量運算,使用expr或let 9 echo $year 10 year="olympic'"$year #字符串直接連接,不需要連接符 11 echo $year 12 13 #usage of if statement 14 if [ $year = 1999 ] 15 then 16 echo "greate" 17 else 18 echo "not greate" 19 fi #語句使用相反的單詞結束 20 21 #usage of function and local variable 22 function echoyear { 23 local year=1998; #局部變量使用local修飾 24 echo $year 25 } 26 echo $year; 27 echoyear; #函數調用 28 29 #usage of for loop 30 for day in Sun Mon Tue Ooo #for語句,day為循環變量,in后面的是循環內容 31 do 32 echo $day 33 done 34 35 # usage of while loop and array 36 users=(Jim Liu Dick Jack Rose) #數組賦值 37 i=0 38 while [ ! -z ${users[$i]} ] #數組取值使用${users[$i]} 39 do 40 echo ${users[$i]} 41 i=`expr $i + 1` 42 done 43 44 # usage of util 45 var="I'm not empty" 46 until [ -z "$var" ];do #字符串變量需要用雙引號括起,否則會拋出"too many argumet"異常,因為腳本會認為每個空格隔開的字符串都是一個參數47 48 echo $var 49 var= 50 done 51 52 # usage of case and input from keyboard 53 echo "Hit a key, then press return" 54 read Keypress #從鍵盤讀入輸入 55 56 case "$Keypress" in #使用case語句 57 [a-z]) echo "Lowercase letter";; #選擇符可以使用正則匹配 58 [A-Z]) echo "Uppercase letter";; 59 [0-9]) echo "Digit";; 60 *) echo "Other";; 61 esac 62 63 # usage of function 64 function pow() { #函數參數使用$1, $2表示第一個參數和第二個參數,以此類推 65 local res=`expr $1 \* $1` # use \* instead of * here 66 return $res 67 } 68 param=5 69 pow $param #函數傳參 70 result=$? #$?代表函數返回值,$#代表參數個數,$@代表所有參數集合 71 echo $result 72 73 # usage of random digit 74 a=$RANDOM #隨機數的使用 75 echo $a 76 77 # usage of select 78 OPTIONS="Hello Quit" 79 select opt in $OPTIONS $使用select自動產生選項供用戶選擇 80 do 81 case $opt in 82 "Hello") 83 echo "Hello There" 84 ;; 85 "Quit") 86 echo "Done" 87 ;; 88 *) 89 echo "Bad Option"
;; 90 esac 91 done 92 93 # usage of read 94 echo "Insert your name"; 95 read name #鍵盤輸入數據 96 echo "Hi "$name