系統管理中 bash shell 腳本經常使用方法總結

FROM: http://www.cnblogs.com/hunterfu/archive/2010/02/23/1672129.htmlhtml

 

在平常系統管理工做中,須要編寫腳原本完成特定的功能,編寫shell腳本是一個基本功了!
在編寫的過程當中,掌握一些經常使用的技巧和語法就能夠完成大部分功能了,也就是2/8原則.linux

1. 單引號和雙引號的區別

單引號與雙引號的最大不一樣在於雙引號仍然能夠引用變量的內容,但單引號內僅是普通字符 ,不會做變量的引用,直接輸出字符竄。請看以下例子:shell

  [root@linux ~]# name=HaHa 
[root@linux ~]# echo $name
HaHa
[root@linux ~]# myname="$name is wow"
[root@linux ~]# echo $myname
HaHa is wow
[root@linux ~]# myname='$name is wow'
[root@linux ~]# echo $myname
$name is wow

從上面例子能夠看出,使用了單引號的時候,那麼$name只是普通字符,直接輸出而已!數組

2. 逐行讀取文件

  • 使用for循環來讀取文件
      for line in `cat file.txt`
    do
    echo $line
    done
注意:因爲使用for來讀入文件裏的行時,會自動把空格和換行符做爲同樣分隔符,若是行裏有空格的時候,輸出的結果會很亂,因此只適用於行連續不能有空格或者換行符的文件
  • 使用while循環讀取文件
      cat file.txt |while read line
    do
    echo $line
    done

    或者:

    while read line
    do
    echo $line
    done < file.txt
注意:因爲使用while來讀入文件裏的行時,會整行讀入,不會關注行的內容(空格..),因此比for讀文件有更好的適用性,推薦使用while循環讀取文件

3. bash shell 腳本中經常使用隱含變量

$0 當前執行的腳本或者命令名稱
$1-$9 表明參數的位置. 舉例 $1 表明第一個參數.
$# 腳本調用的參數的個數
$@ 全部參數的內容
$* 全部參數的內容
$$ 當前運行腳本的進程號
$? 命令執行後返回的狀態
$! 後臺運行的最後一個進程號
注意: $? 用於檢查上一個命令執行是否正確(在Linux中,命令退出狀態爲0表示該命令正確執行,任何非0值表示命令出錯) 
$$ 變量最多見的用途是用作暫存文件的名字以保證暫存文件不會重複。 
$* 和 $@ 若是輸出是同樣的,可是在使用for循環,在使用 雙引號("")引用時 "$*" 會輸出成一個元素 而 "$@" 會按照每一個參數是一個元素方式輸出

請看測試例子bash

  #cat test.sh 
#!/bin/sh
echo '"$@" output.....'
for i in "$@"
do
echo $i
done
echo '"$*" output ....'
for i in "$*"
do
echo $i
done

輸出結果測試

  #sh test.sh a b c d
"$@" output.....
a
b
c
d
"$*" output ....
a b c d
從輸出結果能夠看出 "$*" 輸出是一行 而 "$@" 輸出則是四行

4. 變量內容的刪除與替換

咱們在一些狀況下,須要對變量中的字符竄進行查找刪除或者替換,就須要使用下表列出的方法spa

變量設定方式 說明
${變量#關鍵字} 若變量內容從頭開始的資料符合‘關鍵字’,則將符合的最短資料刪除
${變量##關鍵字} 若變量內容從頭開始的資料符合‘關鍵字’,則將符合的最長資料刪除
${變量%關鍵字} 若變量內容從尾向前的資料符合‘關鍵字’,則將符合的最短資料刪除
${變量%%關鍵字} 若變量內容從尾向前的資料符合‘關鍵字’,則將符合的最長資料刪除
${變量/舊字串/新字串} 若變量內容符合‘舊字串’則‘第一個舊字串會被新字串取代
${變量//舊字串/新字串} 若變量內容符合‘舊字串’則‘所有的舊字串會被新字串取代

舉例以下(刪除字符竄中的某個字符):.net

  [root@linux ~]# export test_str="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" 
[root@linux ~]# echo ${test_str#/*kerberos/bin:}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

5. 變量條件測試賦值

在某些時刻咱們須要‘判斷’某個變量是否存在,若變量存在則將此變量值賦值給新的變量,若變量不存在則將其餘值賦值給新的變量.rest

變量設定方式 str 未定義 str 爲空字串 str 已賦值爲非空字串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str?expr} expr 輸出至 stderr var= var=$str
var=${str:?expr} expr 輸出至 stderr expr 輸出至 stderr var=$str
var=${str=expr} var=expr var= var=$str
var=${str:=expr} var=expr var=expr var=$str

舉例以下:htm

  [root@linux ~]# test_name=""
[root@linux ~]# test_name=${test_name-root}
[root@linux ~]# echo $test_name
<== 由於 test_name 被設定爲空字符竄!因此固然仍是保留爲空字符竄!
[root@linux ~]# test_name=${test_name:-root}
[root@linux ~]# echo $test_name
root <== 加上‘:’後若變量內容爲空或者是未設定,都可以之後面的內容替換!
基本上這種變量的測試也可以透過 shell script 內的 if...then... 來處理,不過經過上述說起的簡單的方法來測試變量,是程序看起來更精簡一些!

6. shell 中分隔符 : 變量IFS 使用

shell腳本中,若是使用for循環一個字符竄的話,默認使用空格來分割字符竄.還有前面所提到的 使用for循環逐行讀取文件內容時候,文件行中若是有空格的話輸出的結果也會變亂.這個時候 使用 IFS 變量來設置特定的字符竄分割符來,達到輸出正確的目的.默認狀況下 IFS 是使用 <space><tab><newline>, 空格 \t \n 來做爲默認的分割符的.

咱們將前面使用for逐行讀取文件的例子 改進下就能夠輸出正確了,請看下面

  #!/bin/bash
IFS_old=$IFS #將原IFS值保存,以便用完後恢復
IFS=$’\n’ #更改IFS值爲$’\n’
for line in `cat file.txt`
do
echo $line
done

file.txt 文件內容以下

  [root@linux]$ cat file.txt 
sdfsdfsdfsdf
ssssss ssssss ssssss sssss
sdfsdfsdfsdfsdf

執行測試程序 輸出結果以下(正確輸出)

  [root@linux]$ sh test.sh 
sdfsdfsdfsdf
ssssss ssssss ssssss sssss
sdfsdfsdfsdfsdf

若是未設置IFS變量,使用默認的IFS變量值 ,輸出結果以下

  [root@linux]$ sh test.sh 
sdfsdfsdfsdf
ssssss
ssssss
ssssss
sssss
sdfsdfsdfsdfsdf

從以上測試程序輸出結果,能夠根據本身的需求來設定 IFS變量,在舉一個例子以下:

  while IFS=: read userName passWord userID groupID geCos homeDir userShell
do
echo "$userName -> $homeDir"
done < /etc/passwd

7. shell 數組的使用

數組賦值方式:

  (1) array=(var1 var2 var3 ... varN)
(2) array=([0]=var1 [1]=var2 [2]=var3 ... [n]=varN)
(3) array[0]=var1
arrya[1]=var2
...
array[n]=varN

計算數組元素個數或者長度:

  (1) ${#array[@]}    
(2) ${#array[*]}

瞭解了數組基礎語法,舉例說明,請看:

  #!/bin/bash
NAMESERVERS=("ns1.www.net." "ns2.www.net." "ns3.www.net.")
# 獲得數組長度
tLen=${#NAMESERVERS[@]}

# 循環數組
for (( i=0; i<${tLen}; i++ ));
do
echo ${NAMESERVERS[$i]}
done

在看一個複雜一點的例子,將文件內容讀取到數組中:

  #!/bin/bash

# 設置IFS將分割符 設置爲 換行符(\n)
OLDIFS=$IFS
IFS=$'\n'

# 讀取文件內容到數組
fileArray=($(cat file.txt))

# restore it
IFS=$OLDIFS
tLen=${#fileArray[@]}

# 循環顯示文件內容
for (( i=0; i<${tLen}; i++ ));
do
echo "${fileArray[$i]}"
done

8. 邏輯判斷 條件測試

  • 文件屬性的判斷
操做符 測試結果
-e filename 文件存在返回1, 不然返回0
-r filename 文件可讀返回1,不然返回0
-w filename 文件可寫返回1,不然返回0
-x filename 文件可執行返回1,不然返回0
-o filename 文件屬於用戶本人返回1, 不然返回0
-z filename 文件長度爲0返回1, 不然返回0
-f filename 文件爲普通文件返回1, 不然返回0
-d filename 文件爲目錄文件時返回1, 不然返回0

舉例以下,測試文件是否存在:

  #!/bin/bash
echo "checks the existence of the messages file."
echo -n "Checking..."
if [ -f /var/log/messages ];then
echo "/var/log/messages exists."
fi
echo
echo "...done."
  • 字符串比較
操做符 比較結果
str1 = str2 當兩個字串相等時爲真
str1 != str2 當兩個字串不等時爲真
-n str1 當字符串的長度大於0時爲真
-z str1 當字符串的長度爲0時爲真
str 當字符串爲非空時爲真

舉例以下,比較字符串來測試用戶ID :

  if [ "$(whoami)" != 'root' ]; then
echo "You have no permission to run $0 as non-root user."
exit 1;
fi
  • 數值比較(整數)
操做符 比較結果
num1 -eq num2 兩數相等爲真
num1 -ne num2 兩數不等爲真
num1 -gt num2 num1大於num2爲真
num1 -ge num2 num1大於等於num2爲真
num1 -lt num2 num1小於num2爲真
num1 -le num2 num1小於等於num2爲真

舉例以下:

  num=`wc -l work.txt`
if [ $num -gt 150 ];then
echo "you've worked hard enough for today."
echo
fi

若是要查看詳細的測試操做,能夠查看man手冊 man test

相關文章
相關標籤/搜索