標籤:des style blog http color io os 使用 ar
1.變數
a.需要給變數賦值時,可以這麼寫:
b.要取用一個變數的值,只需在變數名前面加一個$ ( 注意: 給變數賦值的時候,不能在"="兩邊留空格 )
c.然後執行 chmod +x first 使其可執行,最後輸入 ./檔案名稱 執行該指令碼。
#!/bin/bash# 對變數賦值:a="hello world" #等號兩邊均不能有空格存在# 列印變數a的值:echo "A is:" $a
如果變數與字串混合,則按此方法
num=2echo "this is the ${num}nd"
需要注意shell的預設賦值是字串賦值
var=1var=$var+1echo $var #結果為1+1,不是2
推薦採用以下方法
let "var+=1" #方法1var="$[$var+1]" #方法2 ((var++)) #方法3var=$(($var+1)) #方法4 註:前2種方式在bash下有效,在sh下會出錯。
2.if 語 句
if ....; then ....elif ....; then ....else ....fi
大多數情況下,可以使用測試命令來對條件進行測試,比如可以比較字串、判斷檔案是否存在及是否可讀等等……通常用" [ ] "來表示條件測試,注意這裡的空格很重要,
要確保方括弧前後的空格。
-
[ -f "somefile" ] :判斷是否是一個檔案
-
[ -x "/bin/ls" ] :判斷/bin/ls是否存在並有可執行許可權
-
[ -n "$var" ] :判斷$var變數是否有值
-
[ "$a" = "$b" ] :判斷$a和$b是否相等
-
例如:
#!/bin/bashif [ ${SHELL} = "/bin/bash" ]; then echo "your login shell is the bash (bourne again shell)"else echo "your login shell is not bash but ${SHELL}"fi
變數$SHELL包含有登入shell的名稱,我們拿它和/bin/bash進行比較以判斷當前使用的shell是否為bash。
3.&& 和 || 操作符
#!/bin/bashmailfolder=/var/spool/mail/james[ -r "$mailfolder" ] || { echo "Can not read $mailfolder" ; exit 1; }echo "$mailfolder has mail from:"grep "^From " $mailfolder
該指令碼首先判斷mailfolder是否可讀,如果可讀則列印該檔案中的"From" 一行。如果不可讀則或操作生效,列印錯誤資訊後指令碼退出。需要注意的是,這裡我們必須使用如下兩個命令:
-
-列印錯誤資訊
-
-退出程式
我們使用花括弧以匿名函數的形式將兩個命令放到一起作為一個命令使用;普通函數稍後再作說明。即使不用與和或操作符,我們也可以用if運算式完成任何事情,但是使用與或操作符會更便利很多 。
4.case 語句
case ... in ...) do something here ;;esac
例如:製作一個smartzip指令碼,該指令碼可以自動解壓bzip2, gzip和zip 類型的壓縮檔
#!/bin/bash ftype="$(file "$1")" case "$ftype" in "$1: Zip archive"*) unzip "$1" ;; "$1: gzip compressed"*) gunzip "$1" ;; "$1: bzip2 compressed"*) bunzip2 "$1" ;; *) echo "File $1 can not be uncompressed with smartzip";; esac
你可能注意到上面使用了一個特殊變數$1,該變數包含有傳遞給該指令碼的第一個參數值。也就是說,當我們運行:
smartzip articles.zip
$1 就是字串 articles.zip。
5.select 語句
select var in ... ; do break;done.... now $var can be used ....
例如:
#!/bin/bashecho "What is your favourite OS?"select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do break;doneecho "You have selected $var"
該指令碼的運行結果如下:
What is your favourite OS?1) Linux2) Gnu Hurd3) Free BSD4) Other#? 1You have selected Linux
6.while/for 迴圈
while ...; do ....done
只要測試運算式條件為真,則while迴圈將一直運行。關鍵字"break"用來跳出迴圈,而關鍵字”continue”則可以跳過一個迴圈的餘下部分,直接跳到下一次迴圈中。
for迴圈會查看一個字串列表(字串用空格分隔),並將其賦給一個變數:
for var in ....; do ....done
下面的樣本會把A B C分別列印到螢幕上:
#!/bin/bashfor var in A B C ; do echo "var is $var"done
下面是一個實用的指令碼showrpm,其功能是列印一些RPM包的統計資訊:
#!/bin/bash# list a content summary of a number of RPM packages# USAGE: showrpm rpmfile1 rpmfile2 ...# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpmfor rpmpackage in "[email protected]"; do if [ -r "$rpmpackage" ];then echo "=============== $rpmpackage ==============" rpm -qi -p $rpmpackage else echo "ERROR: cannot read file $rpmpackage" fidone
這裡出現了第二個特殊變數[email protected],該變數包含有輸入的所有命令列參數值。如果你運行showrpm openssh.rpm w3m.rpm webgrep.rpm,那麼 "[email protected]"(有引號) 就包含有 3 個字串,即openssh.rpm, w3m.rpm和 webgrep.rpm。$*的意思是差不多的。但是只有一個字串。如果不加引號,帶空格的參數會被截斷。
7.Shell裡的一些特殊符號
在向程式傳遞任何參數之前,程式會擴充萬用字元和變數。這裡所謂的擴充是指程式會把萬用字元(比如*)替換成適當的檔案名稱,把變數替換成變數值。我們可以使用引號來防止這種擴充,先來看一個例子,假設在目前的目錄下有兩個jpg檔案:mail.jpg和tux.jpg。
- 單引號字串中不能出現單引號(對單引號使用轉義符後也不行)
#!/bin/bashecho *.jpg
運行結果為:
mail.jpg tux.jpg
引號(單引號和雙引號)可以防止萬用字元*的擴充:
#!/bin/bashecho "*.jpg"echo ‘*.jpg‘
其運行結果為:
*.jpg*.jpg
其中單引號更嚴格一些,它可以防止任何變數擴充;而雙引號可以防止萬用字元擴充但允許變數擴充:
#!/bin/bashecho $SHELLecho "$SHELL"echo ‘$SHELL‘
運行結果為:
/bin/bash/bin/bash$SHELL
此外還有一種防止這種擴充的方法,即使用逸出字元——反斜杆:\:
echo \*.jpgecho \$SHELL
輸出結果為:
*.jpg$SHELL
8.Here Document
當要將幾行文字傳遞給一個命令時,用here document是一種不錯的方法。對每個指令碼寫一段協助性的文字是很有用的,此時如果使用here document就不必用echo函數一行行輸出。Here document以 << 開頭,後面接上一個字串,這個字串還必須出現在here document的末尾。下面是一個例子,在該例子中,我們對多個檔案進行重新命名,並且使用here document列印協助:
#!/bin/bash# we have less than 3 arguments. Print the help text:if [ $# -lt 3 ] ; thencat << HELPren -- renames a number of files using sed regular expressions USAGE: ren ‘regexp‘ ‘replacement‘ files...EXAMPLE: rename all *.HTM files in *.html: ren ‘HTM$‘ ‘html‘ *.HTMHELP #這裡HELP要頂格寫,前面不能有空格或者TAB定位字元。如果cat一行寫成cat << -HELP,前邊可以帶TAB. exit 0fiOLD="$1"NEW="$2"# The shift command removes one argument from the list of# command line arguments.shiftshift# [email protected] contains now all the files:for file in "[email protected]"; do if [ -f "$file" ] ; then newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"` if [ -f "$newfile" ]; then echo "ERROR: $newfile exists already" else echo "renaming $file to $newfile ..." mv "$file" "$newfile" fi fidone
第一個if運算式判斷輸入命令列參數是否小於3個 (特殊變數$# 表示包含參數的個數) 。如果輸入參數小於3個,則將協助文字傳遞給cat命令,然後由cat命令將其列印在螢幕上。列印協助文字後程式退出。如果輸入參數等於或大於3個,我們就將第一個參數賦值給變數OLD,第二個參數賦值給變數NEW。下一步,我們使用shift命令將第一個和第二個參數從參數列表中刪除,這樣原來的第三個參數就成為參數列表$*的第一個參數。然後我們開始迴圈,命令列參數列表被一個接一個地被賦值給變數$file。接著我們判斷該檔案是否存在,如果存在則通過sed命令搜尋和替換來產生新的檔案名稱。然後將反短斜線內命令結果賦值給newfile。這樣我們就達到了目的:得到了舊檔案名稱和新檔案名稱。然後使用 mv命令進行重新命名。
9.Shell裡的函數
functionname(){# inside the body $1 is the first argument given to the function# $2 the second ...body}
下面是一個名為xtitlebar的指令碼,它可以改變終端視窗的名稱。這裡使用了一個名為help的函數,該函數在指令碼中使用了兩次:
#!/bin/bashhelp(){cat << HELPxtitlebar -- change the name of an xterm, gnome-terminal or kde konsoleUSAGE: xtitlebar [-h] "string_for_titelbar"OPTIONS: -h help textEXAMPLE: xtitlebar "cvs"HELPexit 0}# in case of error or if -h is given we call the function help:[ -z "$1" ] && help #判斷 $1 這個變數是不是Null 字元串 如果是,則返回真
[ "$1" = "-h" ] && help
# send the escape sequence to change the xterm titelbar:
echo -e "\033]0;$1\007"
#
在指令碼中提供協助是一種很好的編程習慣,可以方便其他使用者(和自己)使用和理解指令碼。
字串操作拼接字串
your_name="qinjx"greeting="hello, "$your_name" !"greeting_1="hello, ${your_name} !"echo $greeting $greeting_1
擷取字串長度:
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`#輸出:8,這個語句的意思是:找出單詞is在這名話中的位置
可以使用source和.關鍵字,如:
source ./function.sh. ./function.sh
在bash裡,source和.是等效的,他們都是讀入function.sh的內容並執行其內容(類似PHP裡的include),為了更好的可移植性,推薦使用第二種寫法。
包含一個檔案和在執行一個檔案一樣,也要寫這個檔案的路徑,不能光寫檔案名稱,比如上述例子中:
. ./function.sh
不可以寫作:
. function.sh
如果function.sh是使用者傳入的參數,如何獲得它的絕對路徑呢?方法是:
real_path=`readlink -f $1`#$1是使用者輸入的參數,如function.sh. $real_path
shell編程筆記(基本部分)