201307311715[Shell Script] 簡單說明

Shell Script 在做 UNIX 系統管理時是個很方便的簡易語言,例如簡單的分析 LOG 檔,或是分析登入該台主機前15名的IP位址跟次數,就可以使用一行指令「 last | awk '{print $3}' | sort | uniq -c | sort -rn | head -15 」就搞定。在 UNIX 系統並沒什麼副檔名代表可以執行,只要權限設定有  chmod +x 就可以執行,一般來說我們會用 .sh 來表示這是一個 Shell Script 檔案。

底下以這些例子來作為說明:

  • 最簡單的 Shell Script
  • 輸入參數、For 迴圈
  • 執行的結果存入變數
  • 輸入文字、判斷 yes/no、if..then..else..fi 判斷式
  • 判斷某目錄是否存在,不存在則建立
  • 讀取檔案的內容
  • 字串處理、字串合併、字串大小寫轉換
  • while 迴圈從 1 印到10
  • Function 功能模組化、Case 用法

 

最簡單的 Shell Script

#!/bin/bash

echo "--- 印出前15名登入次數最多的IP --- "

last | awk '{print $3}' | sort | uniq -c | sort -rn | head -15 

第一行宣告要用 /bin/bash 來執行這個 Script (不同的 Shell 有不同的語法格式,建議大家用 bash)
第一行以「#!」開頭表示以那個 Shell 來執行,不可有空白或其他符號出現,不然會被當成一般的指令

第二行利用 echo 指令印出提示字元
第三行印出前15名登入次數最多的IP,而「 | 」的用意就是將前面所產出的結果傳給後面的指令來處理。 
註解使用符號「#」,所有 #後的字元都會被忽略 
若指令太長、超過一行,可以使用符號「 \ 」來接續、延伸到下一行 。這個
\ 」符號也可以用來取消某些符號的特殊意義,例如 ' " $ ` ,這通常用在顯示輸出這個特殊符號的時候。

 

輸入參數、for 迴圈
假設執行 MyScript AA BB CC  這當中有三個參數,在 Scirpt 程式裡可以用 $1 $2 $3 來帶入、讀取輸入的參數,其他內建變數還有:
$?:程式執行狀態的傳回值
$#:輸入參數的數量
$*:代表所有輸入參數
$@:代表所有輸入參數,可以用來依序表示各個輸入參數
$$:這個 Shell 執行的 PID ( Process ID )

 

知道了輸入參數怎麼抓,再來就是利用 for 迴圈 loop來一個一個抓出來 

for var in "$@"
do
echo $var
done 

問:若上個 Shell Script 是用 $* 會變成什麼結果呢?

 

將執行的結果存入變數裡
一般我們要指定某個變數值,不需要先宣告只要寫「var1=100」或 「var2="Today is good day!" 」要取出來用則加上「$」,例如「echo $var1」
 
最常用的時機在檔案命名或是時間有關的時候,請看底下例子 「將每日備份結果寫到記錄檔」

#!/bin/bash

TODAY=`date +%Y%m%d_%H%M`

BACKUPNAME="Syslog_$TODAY.log"

rsync -av --delete --exclude-from=/shells/none /Source /Destination >> /shells/$BACKUPNAME
 

 

如果在程式中需要得到或計算某個結果,例如某個檔案的行數,你可以簡單的使用

#!/bin/bash
echo "檔案 $filename 內容總共 " ; echo -n $(wc -l $filename) ; echo "行!"

 

輸入文字、判斷 yes/no、if..then..else..fi 判斷式

#!/bin/bash
echo -n "請輸入大名:"
read uname
echo "歡迎 $uname 的到臨"
echo -n "你確定要刪除所有 htdocs 目錄內的檔案嗎? (y/n) ?" 
read check 
if [ "$check" == "Y" -o "$check" == "y" ]; then
rm -rf htdocs
echo "刪除完成!"
else
echo "不亂刪除是好的行為!"
fi 

執行的結果:

[man@good tmp]$ ./a.sh
請輸入大名:Jerry
歡迎 Jerry 的到臨
你確定要刪除所有 htdocs 目錄內的檔案嗎? (y/n) ?n
不亂刪除是好的行為!
[man@good tmp]$ ./a.sh
請輸入大名:Greenth
歡迎 Greenth 的到臨
你確定要刪除所有 htdocs 目錄內的檔案嗎? (y/n) ?y

 
判斷某目錄是否存在,不存在則建立
#!/bin/bash
if [ -d /shells/log1_"$1" ]; then
echo -n "目錄 /shells/log1_" ; echo -n $1; echo " 已經存在!"
else
mkdir /shells/log1_$1
echo "建立子目錄 log1_$1"
fi
 

如果是要判斷檔案則用「-f」參數

 

讀取檔案的內容
在這個例子中,檔案 a.log 裡頭一行就是一串文字,我們利用 while 迴圈來讀取裡面的內容,接著印出來 

#!/bin/bash
filename="/shells/a.log"
exec < $filename
while read var
do
echo $var
done

 

字串處理、字串合併、字串大小寫轉換

#!/bin/bash
test="0123aabbcc!q1234.ww"
filename="Jerry_20130731.tar.gz"
echo "原始字串 $test"
echo "取出字元
位置 2 開始取 5 的字元 : ${test:2:5}"
echo "尋找符合的字串 12 -> #*12 = ${test#*12}.... #*12 = ${test##*12}"
echo "取出檔名 %%.* = ${filename%%.*} ... %.* = ${filename%.*}"
echo "取出特定特徵 %%!q* = ${test%%!q*}"
echo "取出特定特徵 ##*. = ${test##*.}"
xcombine=${test%%!q*}"---"${test##*.}
echo "字串合併 %%!q* + ##*. = $xcombine" 
echo "大小寫轉換"ABcD | tr [A-Z] [a-z]

執行的結果:

原始字串 0123aabbcc!q1234.ww
取出字元位置 2 開始取 5 個字元 : 23aab
尋找符合的字串 12 -> #*12 = 3aabbcc!q1234.ww.... #*12  = 34.ww
取出檔名 %%.* = Jerry_20130731 ... %.* = Jerry_20130731.tar
取出特定特徵 %%!q* = 0123aabbcc
取出特定特徵 ##*. = ww
字串合併 %%!q* + ##*. = 0123aabbcc---ww
大小寫轉換abcd

 

while 迴圈從 1 印到10

#!/bin/bash
i=0
while [ $i -le 10 ]
do
echo -n "$i "
i=`expr $i + 1`
done
echo " .... ok!"
 

-----或者底下這種寫法 ----------

for var in `seq 10`
do
echo $var
done
 

注意:在 expr 的 ` 符號是位於鍵盤上 Tab 鍵的上面那個按鈕

 

Function 功能模組化、Case 用法

#!/bin/bash
function translate () {
case $1 in
1)
echo "壹"
;;
2)
echo "貳"
;;
*)
echo "Others"
;;
esac
}
translate 2
 

Function 的呼叫方式為上面例子的最後一行,因為UNIX的 Shell Script 為逐行直譯式的語言,所以 Function 程式片段必須早於呼叫期間

 

Reference:

~End

回應
Google Search
Google
累積 | 今日
loading......
平均分數:0 顆星
投票人數:0
我要評分:
Google