shell基礎程式設計例項
shell 程式設計 例項
案例:
- 字串擷取 ?
使用 ${} 怎麼做 擷取?
[[email protected] ~]# SCHOOL="Tarena IT Group."
[[email protected] ~]# echo ${#SCHOOL}
16
[[email protected] ~]# echo ${SCHOOL::6}
Tarena
[[email protected] ~]# echo ${SCHOOL:0:6}
Tarena
arena
[[email protected] ~]#
使用expr substr 怎麼擷取?
[[email protected] ~]# SCHOOL="Tarena IT Group."
[[email protected] ~]# expr substr "$SCHOOL" 1 6 //必須加引號 注意
Tarena
使用 cut 工具 怎麼分隔?
[[email protected] ~]# SCHOOL="Tarena IT Group."
[[email protected] ~]# echo $SCHOOL | cut -b 1-6
Tarena
[[email protected] ~]# echo $SCHOOL | cut -b -6
Tarena
[[email protected] ~]# echo $SCHOOL | cut -b 8-
IT Group.
[[email protected] ~]# echo $SCHOOL | cut -b 9
T
字串怎麼 替換?
[[email protected] ~]# SCHOOL="Tarena IT Group."
[[email protected] ~]# echo ${SCHOOL/r/XXX}
TaXXXena IT Group.
[[email protected] ~]# echo ${SCHOOL//r/XXX}
TaXXXena IT GXXXoup.
[[email protected] ~]# echo ${SCHOOL/$SCHOOL/xxx}
xxx
字串怎麼匹配刪除 ?
[[email protected] ~]# echo $MAIL
/var/spool/mail/root
[[email protected] ~]# echo ${MAIL#*oo}
l/mail/root
[[email protected] ~]# echo ${MAIL##*oo}
t
[[email protected] ~]# echo ${MAIL##*/}
root
[[email protected] ~]# echo $MAIL
/var/spool/mail/root
[[email protected] ~]# echo ${MAIL%oo*}
/var/spool/mail/r
[[email protected] ~]# echo ${MAIL%%oo*}
/var/sp
批量修改當前目錄下的副檔名 將.doc 改為.txt?
[[email protected] ~]# more rename.sh
#!/bin/bash
for FILE in *.doc
do
mv $FILE ${FILE%.doc}.txt
done
帶引數 $1, $2 如: ./rename.sh .txt .doc
[[email protected] ~]# more rename.sh
#!/bin/bash
for FILE in *"$1"
do
mv $FILE ${FILE%$1}"$2"
done
:- 取值; := 取值 加賦值 ?
[[email protected] ~]# echo $SCHOOL
Tarena IT Group
[[email protected] ~]# echo ${SCHOOL:-Tarena}
Tarena IT Group
[[email protected] ~]# echo $SCHOOL
Tarena IT Group
[[email protected] ~]# unset SCHOOL
[[email protected] ~]# echo ${SCHOOL:-Tarena}
Tarena
[[email protected] ~]# echo $SCHOOL
[[email protected] ~]#
//變數值不存在情況
[[email protected] ~]# echo $SCHOOL
[[email protected] ~]# echo ${SCHOOL:=Tarean}
Tarean
[[email protected] ~]# echo $SCHOOL
Tarean
//變數值存在的情況
[[email protected] ~]# echo $SCHOOL
Tarean
[[email protected] ~]# echo ${SCHOOL:=Tarena IT Group.}
Tarean
[[email protected] ~]# echo $SCHOOL
Tarean
從鍵盤讀入一個正整數x, 求從 1到 x 的和; 當用戶未輸入值時, 為了避免出錯,x賦初值1. ?
[[email protected] ~]# more sumx.sh
#!/bin/bash
read -p "請輸入一個正整數:" x
x=${x:-1}
i=1; SUM=0
while [ $i -le $x ]
do
let SUM+=i
let i++
done
echo "從1到$x的總和是:$SUM"
怎麼 運算 預設 1+2 中 1,2 是被當為字串的 怎麼 加減乘除運算 ?
[[email protected] ~]# A=1+2
[[email protected] ~]# echo $A
1+2
[[email protected] ~]# X=24
[[email protected] ~]# A=$X+2
[[email protected] ~]# echo $A
24+2
[[email protected] ~]# declare -i A
[[email protected] ~]# A=1+2
[[email protected] ~]# echo $A
3
[[email protected] ~]# declare -i B=$X+2
[[email protected] ~]# echo $B;
26
//declare -x 可以將區域性變數設定為全域性變數
// -r 是隻讀
怎麼定義陣列, 怎麼獲取元素, 總數等 ?
[[email protected] ~]# MY_SVRS=(www ftp mail club)
[[email protected] ~]# echo ${MY_SVRS[@]}
www ftp mail club
[[email protected] ~]# echo ${MY_SVRS}
www
[[email protected] ~]# echo ${MY_SVRS[0]}
www
[[email protected] ~]# echo ${MY_SVRS[@]:1:2}
ftp mail
[[email protected] ~]# echo ${#MY_SVRS[@]}
4
怎麼 實現 ssh 自動登入指令碼 ,主要用到了什麼功能?
[[email protected] ~]# more ./expect_ssh.sh
#!/usr/bin/expect
set host 192.168.3.154
set user root
set password "123qwe"
spawn ssh [email protected]$host
expect {
"yes/no" {send "yes\r";exp_continue}
"password" {send "123qwe\r"}
}
expect "\[$user\@" { send "pwd >> /tmp/$user.txt; exit\r" }
interact
使用正則表示式 :
[[email protected] ~]# grep '^root|^daemon' /etc/passwd
[[email protected] ~]# grep '^root\|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[[email protected] ~]# grep -E '^root|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[[email protected] ~]# egrep '^root|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
我 只是想判斷是否也有複合正則 ,不需要輸出 怎麼做?
使用 -q ; quiet 靜默
[[email protected] ~]# grep -q '^192.168' /etc/hosts && echo "yes" || echo "no"
怎麼輸出匹配到的行數?
[[email protected] ~]# egrep -c '/sbin/nologin$' /etc/passwd
31
[[email protected] ~]# egrep '/sbin/nologin$' /etc/passwd | wc -l
31
怎麼匹配 某個單詞?怎麼匹配以ll結尾的單詞的行 ?
[[email protected] ~]# egrep '\binit\b' /etc/rc.local
[[email protected] ~]# egrep '\<init\>' /etc/rc.local
[[email protected] ~]# egrep 'll\>' /etc/rc.local
[[email protected] ~]# egrep 'll\b' /etc/rc.local
匹配MAC地址 正則?
- [0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}
郵箱正則?
- [0-9a-zA-Z_.]{3,}@[0-9a-zA-Z.-]{2,}(\.[0-9a-zA-Z-]{2,})+
IP地址正則?
- \<[0-9]{1,3}(\.[0-9]{1,3}){3}\>
sed 命令 例項:
輸出 檔案第一行?
[[email protected] ~]# sed -n '1p' /etc/passwd
刪除 檔案 1-4行文字 ?
[[email protected] ~]# sed '1,4d' rc.local
//注意不用加 -n
直接 刪除原檔案 1-4行 文字。?
使用 -i 選項
[[email protected] ~]# sed -i '1,4d' rc.local
怎麼指定多個編輯指令?比如 輸出 第一行,第四行內容?
使用 -e 或 ; (分號)
[[email protected] ~]# sed -n -e '1p' -e '4p' rc.local
[[email protected] ~]# sed -n '1p;4p' rc.local
[[email protected] ~]# sed -n '{1p;4p}' rc.local
輸出所有行,?相當於 cat命令
[[email protected] ~]# sed -n 'p' rclocal.txt
輸出第 2行及 之後的3行?
[[email protected] ~]# sed -n '2,+3p' rclocal.txt
輸出以 xxx (local) 結尾的 行 ?
[[email protected] ~]# sed -n '/local$/p' rclocal.txt
輸出奇數行?
[[email protected] ~]# sed -n 'p;n' rclocal.txt
輸出偶數行?
[[email protected] ~]# sed -n 'n;p' rclocal.txt
輸出最後一行?
[[email protected] ~]# sed -n '$p' rclocal.txt
輸出檔案的 總的行數?
[[email protected] ~]# sed -n '$=' rclocal.txt
刪除 包含 init , bin的行 ?
[[email protected] ~]# sed '/init/d;/bin/d' rclocal.txt
刪除 不包含init 的行 刪除 ?
!d
[[email protected] ~]# sed '/init/ !d' rclocal.txt
p
[[email protected] ~]# sed -n '/init/p' rclocal.txt
刪除所有空行 ?
^$
[[email protected] ~]# sed '/^$/d' rclocal.txt
替換 s
將 所有行 第一個ll 替換為 “XX” ?
[[email protected] ~]# sed 's/ll/XX/' rclocal.txt
將 所有行 中 所有 ll 替換為 “XX” ?
[[email protected] ~]# sed 's/ll/XX/g' rclocal.txt
將第3行內 的 第2個 “script” 替換為 “XX” ?
[[email protected] ~]# sed '3s/script/XX/2' rclocal.txt
刪除 指定的字串 ?
替換為空
[[email protected] ~]# sed 's/init//g' rclocal.txt
刪除所有的“script” “stuff” 字母 “e” ?
或的關係 要用 \| 來表示
[[email protected] ~]# sed 's/script\|stuff\|e//g' rclocal.txt
去掉3-5 行的註釋?
[[email protected] ~]# sed '3,5s/^#//' rclocal.txt
將 /etc/rc.local 檔案 的第 6-7行 註釋掉 ?
行首新增 #
[[email protected] ~]# sed '6,7s/^/#/' rclocal.txt
將 檔案每行 第1 個字元, 第二個字元交換?
-r 啟用正則擴充套件 \2 引用第二個()匹配到的。
[[email protected] ~]# sed -r 's/^(.)(.)/\2\1/' rclocal.txt
刪除行首 空格 ?
[[email protected] ~]# sed -r 's/^( )+//' rclocal.txt
為檔案中每個大些字母新增 括號?
& 代表 匹配到的 整個字串
[[email protected] ~]# sed 's/[A-Z]/(&)/g' rclocal.txt
[[email protected] ~]# sed -r 's/([A-Z])/(\1)/g' rclocal.txt
對網絡卡 配置檔案 eth0 的修改 :
將IP地址 192.168.3.135 修改為 192.168.3.136 ?
思路 首先 定位到 IPADDR (正則定位)
[[email protected] ~]# sed -i '/IPADDR/s/192.168.3.29/192.168.3.136/' /etc/sysconfig/network-scripts/ifcfg-eth0
sed 的多行操作:
c : 替換指定的行
i :在指定的行之前插入文字
a : 在指定的行 後追加 文字
sed 怎麼整行替換呢:?
修改主機名 ?
c : 替換 指定的行
[[email protected] ~]# sed -i '/^HOSTNAME/cHOSTNAME=liang' /etc/sysconfig/network
在 hosts 檔案中, 新增兩行記錄 (a追加)
[[email protected] ~]# sed -i '$a192.168.3.200 liang1.com\
> 192.168.3.202 liang2.com' /etc/hosts
綜合案例:
找到 使用bash 登入 shell 的本地使用者; 按每行 使用者名稱—》 密碼 儲存到檔案a.log中 ?
#!/bin/bash
> /tmp/getupwd.log ##建立空檔案
sed -n '/:\/bin\/bash$/w /tmp/user.tmp' /etc/passwd ##提取符合條件的帳號記錄
UNUM=$(egrep -c '.' /tmp/user.tmp) ##取得記錄個數
#echo $UNUM
while [ ${i:=1} -le $UNUM ]
do
UREC=$(sed -n "${i}p" /tmp/user.tmp)
#echo $UREC
NAME=${UREC%%:*} ##擷取使用者名稱:記錄去尾
PREC=$(sed -n "/^$NAME:/p" /etc/shadow) ##查詢與使用者名稱對應的密碼記錄
PASS=${PREC#*:} ##掐頭
PASS=${PASS%%:*} ##去尾
echo "$NAME--> $PASS" >> /tmp/getupwd.log ##儲存結果
let i++
done
/bin/rm -rf /tmp/user.tmp
echo "使用者分析完畢,請檢視檔案/tmp/getupwd.log"
二:使用awk 的方案
#!/bin/bash
> /tmp/getupwd.log
awk -F: '/:\/bin\/bash$/{print $1}' /etc/passwd > /tmp/user.tmp ##提取使用者名稱
for NAME in $(cat /tmp/user.tmp)
do
#grep "^$NAME:" i /etc/shadow | awk -F: '{print $1 "--->" $2}' /etc/shadow
#echo $NAME
grep "^$NAME:" /etc/shadow | awk -F: '{print $1 "--->" $2 | "cat >>/tmp/getupwd.log"}'
done
echo "使用者分析完畢,請檢視/tmp/getupwd.log"
/bin/rm -rf /tmp/user.tmp
參考 tts-shell day05練習。
awk 例項:
awk 是 怎麼指定分隔符 呢?
預設是:不指定 就是 空格 或 製表符 做分隔;
[[email protected] ~]# awk -F: '{print $1","$7}' /etc/passwd
[[email protected] ~]# awk -F":" '{print $1","$7}' /etc/passwd
awk 怎麼指定多個分隔符呢?
[[email protected] ~]# awk -F [:/] '{print $1,$10}' /etc/passwd
awk 有哪些內建的變數 ? 當前行號,列數 檔名?
[[email protected] ~]# awk '{print FILENAME,NR}' /etc/passwd
[[email protected] ~]# awk -F[:/] '{print NR,NF}' /etc/passwd
awk 怎麼使用環境變數? 輸出當前使用者的passwd的記錄?
[[email protected] ~]# awk -F: '$1==ENVIRON["USER"]{print $0}' /etc/passwd
統計使用bash 作為登入shell 的使用者總個數?
思路: 在begin 定義 計數變數 ; \< bash 匹配bash
[[email protected] ~]# awk 'BEGIN{x=0}/\<bash$/{x++}END{print x}' /etc/passwd
[[email protected] ~]# egrep -c '\<bash$' /etc/passwd
從ifconfig eth0 提取IP地址?
[[email protected] ~]# ifconfig eth0 | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}'
根分割槽 使用率?
[[email protected] ~]# df -hT / | tail -1 | awk '{print $5}'
分析/etc/passwd 檔案 輸出 列表頭; 使用者資訊,bash資訊,, 尾部:行數, 統計資訊。
[[email protected] ~]# awk -F: 'BEGIN{print "User\tUID\tHome"} \
> {print $1"\t"$3"\t"$6} END{print "Total "NR" lines."}' /etc/passwd
輸出 其中登入shell 不以nologin結尾 的使用者名稱,登入shell資訊?
第七個欄位 !~ 反向匹配
[[email protected] ~]# awk -F: '$7!~/nologin$/{print $1, $7}' /etc/passwd
輸出第3行的使用者記錄?
NR ==3
[[email protected] ~]# awk -F: 'NR==3{print}' /etc/passwd
輸出奇數行的使用者記錄?
[[email protected] ~]# awk -F: 'NR%2==1{print}' /etc/passwd
輸出偶數行的使用者記錄?
[[email protected] ~]# awk -F: 'NR%2==0{print}' /etc/passwd
輸出前3行使用者記錄?
[[email protected] ~]# awk -F: 'NR<=3{print}' /etc/passwd
輸出第3-5 行 使用者記錄?
[[email protected] ~]# awk -F: 'NR>=3 && NR<=5{print}' /etc/passwd
輸出 登入shell 不以nologin 結尾 或者 使用者名稱 以 a 或d 開頭 的文字 ?
[[email protected] ~]# awk -F: '$7!~/nologin$/||$1~/^[ad]/{print}' /etc/passwd
統計檔案中 欄位個數 ?
[[email protected] ~]# awk -F: 'BEGIN{x=0}{x+=NF}END{print "Total "x" fields."}' /etc/passwd
列出100以內 整數中7的倍數 或是含7的數?
[[email protected] ~]# seq 100 | awk '$0%7==0||$0~/7/{print}'
awk 流程控制考察。
統計/etc/passwd 檔案中登入shell不是“/bin/bash” 的使用者個數:?
單分支
[[email protected] ~]# awk -F: 'BEGIN{i=0}{if($7!~/bash$/){i++}}END{print i}' /etc/passwd
統計 /etc/passwd 檔案中UID 小於或等於500, UID 大於500的使用者個數:?
雙分支
[[email protected] ~]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd
統計 /etc/passwd 檔案中登入shell 是 /bin/bash sbin/nologin ,其他使用者 的個數 ?
[[email protected] ~]# awk -F: 'BEGIN{i=0;j=0;k=0}{if($7~/bash$/){i++}else if($7~/nologin$/){j++}else{k++}}END{print i,j,k}' /etc/passwd
統計 /etc/passwd 檔案內 root 出現的次數 ?
[[email protected] ~]# awk -F [:/] 'BEGIN{j=0}{i=1}{while(i<=NF){if($i~/root/){j++} i++}}END{print j}' /etc/passwd
[[email protected] ~]# echo $(cat /etc/passwd) | awk -F "root" '{print NF-1}'
計算從1-100內各整數的總和 ?
[[email protected] ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum += i} print sum}'
[[email protected] ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum += i; if(i==100){print sum}}}'
[[email protected] ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum +=i;}}{}END{print sum}' /etc/passwd
跳過 當前 行 ?
next
[[email protected] ~]# awk 'NF<=2{next}{print}' /etc/rc.local
去處重複的行?
[[email protected] ~]# awk '!a[$0]++' a1.txt
[[email protected] ~]# awk '!a[$0]++{print $0}' a1.txt
統計web 訪問日誌 /var/log/httpd/access_log 統計IP 訪問量 ; 按訪問量排序?
sort ; //-n 按數字排序 -r反序 ;-k2 按第二列排序
[[email protected] ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access.log
[[email protected] ~]# awk '{ip[$1]++}END{for(i in ip){print i, ip[i]}}' access.log | sort -nr -k2
參考 tts-shell day06練習。