兄弟連Linux(九)--Shell程式設計
1、正則表示式
1.1 正則表示式與萬用字元(萬用字元有 * ? [])
正則表示式用來在檔案中匹配符合條件的字串,正則是包含匹配。grep、awk、sed等命令可以支援正則表示式
萬用字元用來匹配符合條件的檔名,萬用字元是完全匹配。ls、fin·
* 前一個字元匹配0次或任意多次
. 匹配除了換行符外任意一個字元
^ 匹配行首。例如:^hello會匹配以hello開頭的行
$ 匹配行尾。例如:hello$會匹配以hello結尾的行
[] 匹配中括號中指定的任意一個字元。只匹配一個字元。例如:[aoeiu]匹配任意一個母音字母,[0-9]匹配任意一個數字,[a-z][0-9]匹配小寫字母和一個數字構成的兩位字元。
[^] 匹配除中括號中的字元以外的任意一個字元。例如:[^0-9]匹配任意一位非數字字元。[^a-z]表示任意一位非小寫字母。
\ 轉義符。用於取消特殊符號的含義
\{n\} 表示其前面的字元恰好出現n次。例如:[0-9]\{4\}匹配4位數字,[1][3-][0-9]\{9\}匹配手機號碼。
\{n,\} 表示其前面的字元出現不少於n次。例如:[0-9]\{2,\}表示兩位及以上的數字
\{n,m\} 表示其前面的字元至少出現n次,最多出現m次。例如:[a-z]\{6,8\}匹配6到8位的小寫字母。
“*”前一個字元匹配
grep “a*” test_rule.txt 匹配所有內容,包括空白行
grep “aa*” test_rule.txt 匹配至少包含有一個a的行
grap “aaa*” test_rule.txt 匹配最少包含兩個連續a的字串
grap “aaaaa*” test_rule.txt 匹配最少包含四個連續a的字串
“.”匹配除了換行符外的任意一個字元
grep “s..d” test_rule.txt 匹配在s和d字母之間一定有兩個字元的單詞
grep “s.*d” text_rule.txt 匹配在s和d字母之間有任意字元
grep “.*” text_rule.txt 匹配所有內容
“^”匹配行首,“$”匹配行尾
grep “^M” test_rule.txt 匹配以大寫M開頭的行
grep “n$” text_rule.txt 匹配以小寫n結尾的行
grep -n “^$” test_rule.txt 匹配空白行
“[]”匹配中括號指定的任意一個字元,只匹配一個字元
grep “s[ao]id” test_rule.txt 匹配s和i字元中間,不是a,就是o
grep “[0-9]” test_rule.txt 匹配任意一個數字
grep “^[a-z]” test_rule.txt 匹配用小寫字母a開頭的行
“[^]”匹配除中括號的字元以外的任意一個字元
grep “^[^a-zA-Z]” test_rule.txt 匹配不用字母開頭的行
grep “^[^a-z]” test_rule.txt 匹配不用小寫字母開頭的行
“\”轉義符
grep “\.$” test_rule.txt 匹配使用“.”結尾的行
“\{n\}”表示其前面的字元恰好出現n次
grep “a\{3\}” test_rule.txt 匹配a字母連續出現3次的字串
gerp “[0-9]\{3\}” test_rule.txt 匹配包括連續的三個數字的字串
“\{n,m\}”匹配其前面的字元至少出現n次,最多出現m次
grep “sa\{1,3\}i” test_rule.txt
2、字元擷取命令
2.1 cut欄位提取命令
cut -df 檔名
-d 提取第幾列
-f 按照指定分隔符分隔列
2.2 pringf命令
printf ‘輸出型別輸出格式’ 輸出內容
輸出型別
%ns 輸出字串。n是數字指代輸出幾個字串
%ni 輸出整數。n是數字指代輸出幾個數字
%m.nf 輸出浮點數。m和n是數字,指代輸出的整數位數和小數位數。如%8.2f代表共輸出8位數,其中2位是小數,6位是整數
輸出格式
\a 輸出警告聲音
\b 輸出退格鍵,也就是Backspace鍵
\f 清除螢幕
\n 換行
\r 回車,也就是Enter鍵
\t 水平輸出退格鍵,也就是Tab鍵
\v 垂直輸出退格鍵,也就是Tab鍵
2.3 awk命令
$ awk ‘條件1{動作1}條件2{動作2}…’ 檔名
條件(Pattern):
一般使用關係表示式作為條件
x>10 判斷變數x是否大於10
x>=10 大於等於
x<=10 小於等於
動作(Action):
格式化輸出
流程控制語句
BEGIN
$ awk ‘BEGIN {printf “This is a transcript \n”} {printf $2 “\t” $6 “\n”}’ student.txt
FS內建變數
$ cat /etc/passwd | grep “/bin/bash” | awk ‘BEGIN {FS=”:”} {printf $1 “\t” $3 “\n”}’
END
$ awk ‘END {printf “The End \n”}{printf $2 “\t” $6 “\n”}’ student.txt
關係運算符
$ cat student.txt | grep -v Name| awk ‘$6 >=87 {printf $2 “\n”}’
2.4 sed命令
2.4.1 sed命令
sed是一種幾乎包括在所有UNIX平臺(包括Linux)的輕量級流編輯器。sed主要是用來將資料進行選取、替換、刪除、新增的命令。
$ sed -nei ‘[動作]’ 檔名
-n 一般sed命令會把所有資料都輸出到螢幕,如果加入此選擇,則只會把經過sed命令處理的行輸出到螢幕
-e 允許對輸入資料應用多條sed命令編輯
-i 用sed的修改結果直接修改讀取資料的檔案,而不是由螢幕輸出
動作:
a \ 追加,在當前行後新增一行或多行。新增多行時,出最後一行外,每行末尾需要用“\”代表資料未完結
c \ 行替換,用c後面的字串替換原資料行,替換多行時,除最後一行外,每行末尾需用“\”代表資料未完結
i \ 插入,在當前行前插入一行或多行。插入多行時,出最後一行外,每行末尾需要用“\”代表資料未完結
d 刪除,刪除指定的行
p 列印,輸出指定的行
s 字串替換,用一個字串替換另一個字串。格式為“行範圍s/舊字串/新字串/g”(和vim中的替換格式類似)
2.4.2 行資料操作
$ sed -n ‘2p’ student.txt
$ sed ‘2,4d’ student.txt
$ sed ‘2a hello’ student.txt
$ sed ‘2i hello\
world’ student.txt
$ sed ‘2c No such person’ student.txt
2.4.3 字串替換
$ sed ‘s/舊字串/新字串/g’ 檔名
$ sed -i ‘3s/74/99/g’ student.txt
$ sed -e ‘s/Liming//g; s/Gao//g’ student.txt
3、字元處理命令
3.1 排序命令sort
$ sort -fnrtk 檔名
-f 忽略大小寫
-n 以數值型進行排序,預設使用字串型排序
-r 反向排序
-t 指定分隔符,預設的分隔符是製表符
-k n[,m] 按照指定的欄位範圍排序。從第n欄位開始,m欄位結束(預設到行尾)
$ sort /etc/passwd 排序使用者資訊檔案
$ sort -r /etc/passwd 反向排序
$ sort -t “:” -k 3,3 /etc/passwd 指定分隔符是“:”,用第三欄位開頭,第三欄位結尾排序,就是隻用第三欄位排序
$ sort -n -t “:” -k 3,3 /etc/passwd
3.2 統計命令 wc
$ wc -lwm 檔名
-l 只統計行數
-w 只統計單詞數
-m 只統計字元數
4、條件判斷
4.1 按照檔案型別進行判斷
-b 檔案 判斷該檔案是否存在,並且是否為塊裝置檔案(是塊裝置檔案為真)
-c 檔案 判斷該檔案是否存在,並且是否為字元裝置檔案(是字元裝置檔案為真)
-d 檔案判斷該檔案是否存在,並且是否為目錄檔案(是目錄為真)
-e 檔案判斷該檔案是否存在(存在為真)
-f 檔案判斷該檔案是否存在,並且是否為普通檔案(是普通檔案為真)
-L 檔案 判斷該檔案是否存在,並且是否為符號連結檔案(是符號連結檔案為真)
-p 檔案 判斷該檔案是否存在,並且是否為管道檔案(是管道檔案為真)
-s 檔案 判斷該檔案是否存在,並且是否為非空(非空為真)
-S 檔案 判斷該檔案是否存在,並且是否為套接字檔案(是套接字檔案為真)
兩種判斷格式
$ test -e /root/install.log
$ [ -e /root/install.log ]
$ echo $? 檢視上一條命令執行情況
[ -d /root ] && echo “yes” || echo “no” 第一個判斷命令如果正確執行,則列印“yes”,否則列印“no”
4.2 按照檔案許可權進行判斷
-r 檔案判斷該檔案是否存在,並且是否該檔案擁有讀許可權(有讀許可權為真)
-w 檔案判斷該檔案是否存在,並且是否該檔案擁有寫許可權(有寫許可權為真)
-x 檔案判斷該檔案是否存在,並且是否該檔案擁有執行許可權(有執行許可權為真)
-u 檔案 判斷該檔案是否存在,並且是否該檔案擁有SUID許可權(有SUID許可權為真)
-g 檔案 判斷該檔案是否存在,並且是否該檔案擁有SGID許可權(有SGID許可權為真)
-k 檔案 判斷該檔案是否存在,並且是夠該檔案擁有SBit許可權(有SBit許可權為真)
4.3 兩個檔案之間進行比較
檔案1 -nt 檔案2 判斷檔案1的修改時間是否比檔案2的新(如果新則為真)
檔案1 -ot 檔案2 判斷檔案1的修改時間是否比檔案2的舊(如果舊則為真)
檔案1 -ef 檔案2 判斷檔案1和檔案2的Inode號是否一致,可以理解為兩個檔案是否為同一個檔案。這個判斷能用於判斷硬連結是很好的方法
4.4 兩個整數之間的比較
整數1 -eq 整數2 判斷整數1是否和整數2相等(相等為真)
整數1 -ne 整數2 判斷整數1是否和整數2不相等(不相等為真)
整數1 -gt 整數2 判斷整數1是否大於整數2(大於為真)
整數1 -lt 整數2 判斷整數1是否小於整數2(小於為真)
整數1 -ge 整數2 判斷整數1是否大於等於整數2(大於等於為真)
整數1 -le 整數2 判斷整數1是否小於等於整數2(小於等於為真)
4.5 字串的判斷
-z 字串 判斷字串是否為空(為空返回真)
-n 字串 判斷字串是否為非空(非空返回真)
字串1==字串2 判斷字串1是否和字串2相等(相等返回真)
字串1!=字串2 判斷字串1是否和字串年不相等(不相等返回真)
name=sc 給name變數負責
[ -z “$name” ] && echo ”yes” || echo “no” 判斷name變數是否為空,因為不為空,所以返回no
4.6 多重條件判斷
判斷1 -a 判斷2 邏輯與,判斷1和判斷2都成立,最終結果才成立
判斷1 -o 判斷2 邏輯或,判斷1或判斷2有一個成立,最終結果就為真
!判斷 邏輯非,使原始的判斷式取反
aa=11
[ -n “$aa” -a “$aa” -gt 23 ] && echo “yes” || echo “no” 判斷變數aa是否有值,同時判斷變數aa的值是否大於23,所以雖然第一個判斷值為真,返回的結果也是假
5、流程控制
5.1 if語句
5.1.1 單分支if條件語句
if [ 條件判斷式 ] ; then
程式
fi
或者
if [ 條件判斷式 ]
then
程式
fi
單分支條件語句需要注意幾個點:
if語句使用fi結尾,和一般語言使用大括號結尾不同
[ 條件判斷式 ]就是使用test命令判斷,所以中括號和條件判斷式之間必須有空格
then後面跟符合條件之後執行的程式,可以放在[]中,用“;”分隔。也可以換行寫入,就不需要“;”了。
#!/bin/bash
#統計根分割槽使用率
#Author:shenchao(Email:[email protected])
rate=$(df -h | grep “/dev/sda3” | awk ‘{print $5}’ | cut -d “%” -f1) #把根分割槽使用率作為變數值賦予變數rate
if [ $rate -ge 80 ]
then
echo “Warning! /dev/sda3 is full!!”
fi
5.1.2 雙分支if條件語句
if [ 條件判斷式 ]
then
條件成立時,執行的程式
else
條件不成立時,執行的另一個成粗
fi
#!/bin/bash
#備份MySQL資料庫
#Author: shenchao (Email:[email protected])
ntpdate asia.pool.ntp.org &>/dev/null 同步系統時間
date=$(date +%Y%M%d) 把當前系統時間按照“年月日”格式賦予變數date
size=$(du -sh /var/lib/mysql) 統計mysql資料庫大小,並把大小賦予size變數
if [ -d /tmp/dbbak ]
then
echo “Date : $date!” > tmp/dabak/dbinfo.txt
echo “Data size : $size” >> /tmp/dbbak/dbinfo.txt
cd /tmp/dbbak
tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &> /dev/null
rm -rf /tmp/dbbak/dbinfo.txt
else
mkdir /tmp/dbbak
echo “Date: $date!” > /tmp/dbbak/dbinfo.txt
echo “Date size : $size” >> /tmp/dbbak/dbinfo.txt
cd /tmp/dbbak
tar -zcf mysql-lib-$date.tar.gz /varlib/mysql dbinfo.txt &> /dev/null
rm -rf /tmp/dbbak/dbinfo.txt
#!/bin/bash
#判斷Apache是否啟動
#Author:shenchao (Email:[email protected])
prot=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk ‘{print $2}’) 使用nmap命令掃描伺服器,並擷取apache服務的狀態,賦予變數port
if [ “$port” == “open” ]
then
echo “$(date) httpd is ok!” >> /tmp/autostart-acc.log
else
/etc/rc.d/init.d/httpd start &>/dev/null
echo “$(date) restart http !!” >> /tmp/autostart-err.log
fi
5.1.3 多分支if條件語句
if [ 條件判斷式1 ]
then
當條件判斷式1成立時,執行程式1
elif [ 條件判斷式2 ]
then
當條件判斷式2成立時,執行程式2
…省略更多條件…
else
當所有條件都不成立時,最後執行此程式
fi
#!/bin/bash
#判斷使用者輸入的是什麼檔案
# Author: shenchao (Email: [email protected])
read -p “Please input a filename: ” file 接收鍵盤的輸入並賦予變數file
if [ -z “$file” ] 判斷file變數是否為空
then
echo “Error, please input a filename”
exit 1
elif [ ! -e “$file” ] 判斷file的值是否存在
then
echo “Your input is not a file”
exit 2
elif [ -f “$file” ] 判斷file的值是否為普通檔案
then
echo “$file is a regulare file!”
elif[ -d “$file” ] 判斷file的值是否為目錄檔案
then
echo “$file is directory!”
else
echo “$file is an other file!”
fi
5.2 case語句
多分支case條件語句
case語句和if…elif…else語句一樣都是多分支條件語句,不過和if多分支條件語句不同的是,case語句只能判斷一種條件關係,而if語句可以判斷多種條件關係。
case $變數名 in
“值1”)
如果變數的值等於值1,則執行程式1
;;
“值2”)
如果變數的值等於值2,則執行程式2
;;
…省略其他分支…
*)
如果變數的值都不是以上的值,則執行此程式
;;
esac
5.3 for迴圈
語法一
for 變數 in 值1值2值3
do
程式
done
語法二
for ((初始值;迴圈控制條件;變數變化))
do
程式
done
5.4 while迴圈和until迴圈
5.4.1 while迴圈
while迴圈是不定迴圈,也稱為條件迴圈。只要條件判斷式成立,迴圈就會一直繼續,直到條件判斷式不成立,迴圈才會停止。這就和for的固定迴圈不太一樣了。
while [ 條件判斷式 ]
do
程式
done
5.4.2 until迴圈
until迴圈,和while迴圈相反,until迴圈時只要條件判斷式不成立則進行迴圈,並執行迴圈程式。一旦迴圈條件成立,則終止迴圈。
until [ 條件判斷式 ]
do
程式
done