shell 編程初步

變量:命名的內存空間:不一樣類型數據存儲空間不同;
數據存儲方式:
字符:1 如:1 既是字符又是數值;110,24 這種編碼字符集美國成爲ASCII
數值:1,110 --> 0-255 之類,將十進制轉成二進制,八位就夠了,就是一個字節;
整型數值和浮點型數值;存儲一個漢字須要許多的0 和1 來存入到計算機;
計算機內存最小存儲單位爲字節 1字節=8位;統一標準:字符集 來對應中文漢字或者其餘語言;如 gbk;gb18030;utf8;不然會亂碼;英文是127個變換,一個字節足以;
數值:110+12=122 ,11010=1100
字符運算:110+12=11012,110
10=110110110110110110**十次
變量:變量類型
做用:一、數據存儲格式;二、參與的運算;三、表示的數據範圍;
類型:字符;數值(整型(int)和浮點型(float))
編程程序語言:強類型
弱類型:bash :把全部的要存儲的數據統統充當字符進行;不支持浮點型;
布爾型 邏輯運算:true,false 非 異或
與 : 1&&1 =1 ;1&&0=0;0&&1=0; 0&&0=0
或:1||1=1; 1||0=1; 0||1=1; 0||0=0
非: !1=0; !0=1
異或:兩個同時爲真爲假,兩個爲假爲真;
短路運算:
與:
對於與運算,對於左側是0,結果一定是0;第一個爲1,第二個必須參與運算;
或:
第一個爲1,結果一定爲1;第一個爲0,第二個必需要參與運算;
好比: ls /var&&echo 「hello」 若是第一個是成功的,第二個命令必須得運行;
第一個運行失敗了,第二個直接不運行了,短路運算;
ls /var||echo 「hello」第一個成功,第二個不須要執行;第一個失敗,執行第二個;
ls /var&&echo 「success」||echo 「failure」第一個成功,直接返回;第一個失敗,就執行第二個。
id root &> /dev/null &&echo 「exits」||echo 「no such user」
小結:shell基礎特性,grep
Shell: #!/bin/bash
過程式:以命令爲中心
對象式:以數據爲中心
grep:j文本過濾器(支持正則)
PATTERN(魔數)
REGEXP(正則)
BRE(基本正則),ERE(擴展正則)
BRE:字符匹配:‘.’(任意單個字符); ‘[]’(範圍內任意單個字符); ‘[^]’ (範圍外任意單個字符);
次數匹配:‘
’,匹配前面的字符任意次;’(\是轉義)\?’:匹配前面字符0或者1次,無關緊要;+:匹配前面字符至少一次;{m}精確指定次數。
位置錨定:
^:行首指定 :指定模式的最左側
$:行尾指定:指定模式的最右側
^patterns:用於模式匹配整行;
^$:空行;
^[[:space:]]$: 空白行
\< 或者 \b:詞首錨定:用於單詞模式的左側;
\> 或者 \b詞尾錨定:用於單詞模式的右側;
\<PATTERN\>:匹配整個單詞;
分組符號
()
(xy)

grep ‘(xy)+’grep.txt
grep ‘xy+’grep.txt X後面至少跟一個y
NOtice:分組括號中的模式匹配到的內容會被正則表達式引擎記錄於內部的變量中,這些變量的命名方式爲:\1,\2,\3.....
\1:從左側起,第一個左括號以及與之匹配右括號之間的模式所匹配到的字符;
(ab+(xy));
\1:ab+(xy)

\2: xynginx

後向引用:引用前面的分組括號中的模式所匹配字符,(而非模式自己)
grep '([[:alpha:]]{1,3}t\>).*\1' /etc/passwd
Vim,sed,awk,grep ,nginx
bash 腳本編程:
過程式編程語言:
順序執行
選擇執行
循環執行正則表達式

選擇執行:
if 判斷條件;then (單分支if)
條件爲真的分支代碼
結束shell

if 判斷條件;then (雙分支if)
條件爲真的分支代碼
else
條件爲假的分支代碼
fiexpress

vi adduser.sh
#!/bin/bash
if [ $# -lt 1 ];then
echo "at least one argument."編程

if id $1 &> /dev/null;then
echo "$1 exists."
else
useradd $1
[ $? -eq 0 ]&& echo "$1" |passwd --stdin $1 &> /dev/null
fi
多分支:
if condition;then
If-true
Elif condition;then
If-true
Elif condition;then
If-true
......
Else
All-false
Fi
逐條件進行判斷:第一次遇到「真」條件時,執行其分支,然後結束;
示例:用戶鍵入文件路徑,腳原本判斷文件類型;
#!/bin/bash
read -p 「Enter a file path: 」filename
if bash

bash編程之for循環
for 變量名 in 列表; do(跟if 的then 類似,換行「;」能夠省略)
循環體
done
執行機制:
依次將列表中的元素賦值給"變量名",每次賦值後即執行一次循環體;直到列表中的元素耗盡,循環結束;
示例:添加10個用戶,user1---user3,密碼同用戶名;
#!/bin/bash
if [ ! $UID -eq 0 ];then
echo "only root."
exit 1
fi
for username in user1 user2 user3;do
if id $username &> /dev/null;then
echo "$username exists."
else
useradd -M $username
if [ $? -eq o ];then
echo "$username"|passwd --stdin $username &> /dev/null
echo "Add $username finished."
fi
fi網絡

#!/bin/bash
if [ ! $UID -eq 0 ];then
echo "only root."
exit 1
fi
for i in {1..10};do
if id user$i &> /dev/null;then
echo "user$i exists."
else
useradd -M user$i
if [ $? -eq o ];then
echo "user$i"|passwd --stdin user$i &> /dev/null
echo "Add user$i finished."
fi
fitcp

列表生成方式:
(1)直接輸出列表;
(2)整數列表;
(a)in {首數..尾數}(in {1..10})
(b)$(seq [start [step]] end)
(3)返回列表的命令
$(COMMAND)
(4)glob
(b)變量引用
$@,$*編程語言

示例:判斷某路徑下全部文件的類型;
#!/bin/bash
for file in $(ls /var);do (/var/*)
if [ -f /var/$file ];then
echo "common file."
elif [ -L /var/$file ];then
echo "Symbolic file."
elif [ -d /var/$file ];then
echo "Directory."
else
echo "Other type."
fi
doneide

查看tcp狀態腳本
netstat -tan |grep "^tcp>/"|awk "{print $NF}"

#!/bin/bash
estab=0
listen=0
other=0

for status in $(netstat -tan |grep "^tcp>/"|awk "{print $NF}");do
if [ "$status" == "ESTABLISHED" ];then
let estab++
elif [ "$status" == "LISTEN" ];then
let listen++
else
let other++
fi
done
echo "ESTABLISHED: $estab"
echo "LISTEN: $listen"
echo "Unkown: $other"

練習1:/etc/rc.d/rc.d目錄下分別有多個以K開頭和以S開頭的文件;分別讀取每一個文件,以K開頭的文件輸出爲文件名加stop,以S開頭的文件輸出爲文件名加start;
#!/bin/bash
for file in /etc/rc.d/rc.d/*;do

bash編程之while循環
順序執行
選擇執行
條件測試
運行命令或[[ expression ]]
執行狀態返回值:
If
Case
循環執行
將某代碼段重複運行屢次;
重複運行多少次?
循環次數事先已知:
循環次數事先未知:
必須有進入和退出條件:
For, while,until
函數:結構化編程及代碼重用; function
For 循環語法:
For NAME in list; do
循環體
Done
列表生成方式:
(1)整數列表
{start..end}
$(seq start [[step]end])
(2) glob
/etc/rc.d/rc3.d/K*
(3)命令
Bash -n 判斷腳本正確性;bash -x 查看腳本執行流程;
示例: 監測10.0.27.1-20的網絡狀態
#!/bin/bash
#
net="10.0.27"
uphosts=0
douwnhosts=0
for i in {1..21};do
ping -c 1 -t 1 ${net}.${i} &> /dev/null
if [ $? -eq 0 ];then
echo "${net}.${i} is up"
let uphosts++
else
echo "${net}.${i} is down"
let downhosts++
fi
done
echo "UP hosts: $uphosts"
echo "Down hosts: $downhosts"

While 循環:
While CONDITION;do
循環體
Done
CONDITION:循環控制條件
CONDITION::循環控制條件:進入循環以前,先作一次判斷;每一次循環以後會再次作判斷;
條件爲「true」,則執行一次循環;直到條件測試狀態爲false停止循環;
所以CONDITION通常應該有循環控制變量;而此變量的值會在循環體不斷被修正;
示例:求100之內全部正整數之和;
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ];do
let sum+=$i
let i++
done
echo 「$i」
echo 「summary: $sum」

練習:用while批量添加用戶use1---user10;
For與while區別就是 while 要手動控制循環
練習:打印九九乘法表:(分別使用for和while循環實現)

bash腳本編程:
While CONDITION;do
循環體
Done
進入條件:CONDITION爲True
退出條件:false
Until CONDITION;do
循環體
Done
進入條件:false
退出條件:true
示例:求100之內全部正整數之和;
For:
#!/bin/bash
sum=0
i=1
for i in {1..100};do
let sum+=$i
done
echo "$i"
echo "$sum"
While:
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ];do

sum=$[$sum+$i]

let sum+=$i
let i++
done
echo "$i"
echo "$sum"

Until:
#!/bin/bash
i=1
sum=0
until [ $i -gt 100 ];do
let sum+=$i
let i++
done
echo "$i"
echo "$sum"

利用until打印九九乘法表
#!/bin/bash
j=1
i=1
until [ $j -gt 9 ];do
until [ $i -gt $j ];do
echo -n -e "${i}X${j}=$[$i*$j]\t"
let i++
done
echo
let i=1
let j++
done

循環控制語句(用於循環體中):
Countiue
Continue [N] 提早結束第N層的本輪循環,並直接進入下一輪判斷;
While CONDITION1;do
CMD1
......
If CONDITION2;then
Continue
Fi
CMDn
....
done
Break
Break [n] 提早結束循環
CMD1
......
If CONDITION2;then
Brrak
Fi
CMDn
....
done
示例:求100之內全部偶數之和:要求遍歷100之內的全部正整數;
#!/bin/bash
i=0
sum=0
until [ $i -gt 100 ];do
let i++
if [ $[$i%2] -eq 1 ];then
continue
fi
let sum+=$i
Done
;
While true;do
循環體
Done

示例2:用戶選擇,並顯示完成後不退出腳本,而是提示用戶繼續選擇顯示其餘內容:直接使用quit退出;
#!/bin/bash
cat <<EOF
cpu)show cpu information;
mem)show memory information;
disk)show disk information;
quit)quit
#################################
EOF
if [ $UID -gt 0 ];then
echo "Command mast be root."&& exit 1
fi

read -p "Enter a option: " option
while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ];do
read -p "Wrong option!! Enter again: " option
done
if [ "$option" == "cpu" ];then
lscpu
elif [ "$option" == "mem" ];then
cat /proc/meminfo
elif [ "$option" == "disk" ];then
fdisk -l
else
echo "Quit"
fi
示例2:每隔三秒到系統上獲取已登陸的用戶的信息:

條件判斷:case語句
Case 變量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
....
*)
默認分支
;;
Esac

#!/bin/bash
cat <<EOF
cpu)show cpu information;
mem)show memory information;
disk)show disk information;
quit)quit
#################################
EOF
if [ $UID -gt 0 ];then
echo "Command mast be root."&& exit 1
fi

read -p "Enter a option: " option
while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ];do
read -p "Wrong option!! Enter again: " option
done
case "$option" in
cpu)
lscpu
;;
mem)
cat /proc/meminfo
;;
disk)
fdisk -l
;;
*)
echo "Quit...."
exit 0
esac

練習:寫一個腳本,完成 以下需求;(1)腳本可接收參數:start,stop,restart,status;(2)若是參數非此四者之一,提示使用格式後報錯推出;(3)若是是start:則建立/var/lock/subsys/SCRIPT_NAME,並顯示「啓動成功」(4)若是是stop:則刪除/var/lock/subsys/SCRIPT_NAME,並顯示「中止完成」;考慮:若是事先已然中止過了,該如何處理?(5)若是是restart ,則先stop,再start;考慮:若是原本沒有start,如何處理;(6)若是是status,則若是/var/lock/subsys/SCRIPT_NAME文件存在,則顯示「SCRIPT_NAME is running...」;若是/var/lock/subsys/SCRIPT_NAME文件存在,則顯示「SCRIPT_NAME is stopped...」;其中:SCEIPT_NAME爲當前腳本名;

相關文章
相關標籤/搜索