一、for循環
for 變量名 in 列表;do
循環體
done
列表生成方式:
(1) 直接給出列表
(2) 整數列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 變量引用;
$@, $*
例1:
[root@centos6 data]#for i in /data/*.sh;do echo the filename is $i;done
the filename is /data/67_createuser.sh
the filename is /data/checkint.sh
the filename is /data/createuser.sh
the filename is /data/filetype.sh
the filename is /data/if.sh
例2:求100以內的偶數和
#!/bin/bash
#
declare -i sum=0
for i in `seq 2 2 100`;do
let sum+=i
done
echo sum=$sum
例3:腳本內多行重定向寫法
for i in {1..10};do
cat >> f1 <<-EOF
aa
bb
EOF
done
EOF前加上-
例4:創建10個用戶,分別為user1到user10,密碼分別為12345
#!/bin/bash
#
for i in user{1..10};do
if id $i &>/dev/null;then
echo “$i is exist”
else
useradd $i
echo “$i has created”
echo 12345 |passwd –stdin $i &>/dev/null
fi
done
例5:掃描某個網段的所有主機,在線顯示up,不在線顯示down,把在線的主機ip保存到文件中hostup.list
#!/bin/bash
#
net=192.168.67
for i in {1..254};do
{ if ping -c1 -w1 $net.$i &>/dev/null;then
echo “$net.$i is up”
echo $net.$i >> /data/hostup.list
else
echo “$net.$i is down”
fi } &
done
wait
加上{ }加快運行速度,多個程序并行執行,wait表示執行結束自動彈出
二、let命令中 i++與++i 的區別
i++:
[root@centos6 data]#i=0
[root@centos6 data]#let i++
[root@centos6 data]#echo $?
1
++i:
[root@centos6 data]#i=0
[root@centos6 data]#let ++i
[root@centos6 data]#echo $?
0
三、eval命令
[root@centos6 data]#n=3;for i in `eval echo {1..$n}`;do echo num is $i ;done
num is 1
num is 2
num is 3
eval命令會先引用變量$n,讓后在執行echo命令
四、for循環嵌套
for i in {1..10};do
for i in {1..10};do
…
done
done
例1:打印矩形
length=$1
width=$2
for i in `seq 1 $length`;do
for j in `seq 1 $width`;do
color=$[RANDOM%7+31]
bk=$[RANDOM%7+41]
echo -e “\e[1;5;${bk};${color}m*\e[0m\c”
done
echo
done
例2:打印9*9乘法表
for i in {1..9};do
for j in `seq 1 $i`;do
sum=$[i*j]
echo -e “${j}*${i}=${sum}\t\c”
done
echo
done
例3:打印國際象棋
for i in {1..8};do
for k in {1..2};do
if [ $[i%2] -eq 0 ];then
for j in {1..4};do
echo -e “\e[1;42m??? \e[0m\c”
echo -e “\e[1;43m??? \e[0m\c”
done
echo
else
for j in {1..4};do
echo -e “\e[1;43m??? \e[0m\c”
echo -e “\e[1;42m??? \e[0m\c”
done
echo
fi
done
done
例4:打印等腰三角形
#!/bin/bash
#
#********************************************************************
#Author:??????????????? wqf
#QQ:??????????????????? 88888888
#Date:????????????????? 2018-05-08
#FileName:???????????? sanjiaoixng.sh
#URL:?????????????????? http://www.magedu.com
#Description:????????? The test script
#Copyright (C):???????? 2018 All rights reserved
#********************************************************************
read -p “please input line num: ”? line
declare -i linenum=0
for i in `seq 1 $line`;do
let ++linenum
star=$[linenum*2-1]
space=$[line-linenum]
for k in `seq $space`;do
echo -e ” \c”
done
for j in `seq $star`;do
echo -e “*\c”
done
echo
done
[root@centos6 data]#sanjiaoxing.sh
please input line num: 6
*
***
*****
*******
*********
***********
五、while循環
while CONDITION; do
循環體
done
CONDITION:循環控制條件;進入循環之前,先做一次判斷;每一次循環之后會再次做判斷;條件為“true”,則執行一次循環;直到條件測試狀態為“false”終止循環
因此:CONDTION一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正
進入條件:CONDITION為true
退出條件:CONDITION為false
例1:求100以內奇數和
#!/bin/bash
#
declare -i sum=0
declare -i i=1
while [ $i -le 100 ];do
if [ $[i%2] -eq 1 ];then
sum+=i
fi
let i++
done
echo sum=$sum
例2:每7分鐘執行某個命令
[root@centos6 data]#vim ping.sh
#!/bin/bash
#
while true;do
echo task
sleep 420
done
如果要防止腳本意外終端,可以用執行nohup scripts
例3:監控http服務,每10秒檢查一次服務是否重啟,如果沒在線,就重啟
#!/bin/bash
#
SLEEP=10
while true;do
if killall -0 httpd &>/dev/null;then
:
else
systemctl restart httpd
echo “at `date “+%F %T”` restart the httpd” >>/data/httpd.log
sleep $SLEEP
fi
done
killall -0 httpd 判斷httpd服務是否在運行
六、until循環
until CONDITION; do
循環體
done
進入條件: CONDITION 為false
退出條件: CONDITION 為true
例1:如果wang用戶登陸,則退出
#!/bin/bash
#
until w |grep wang &>/dev/null;do
sleep 1
done
echo “find wang login”
七、循環控制語句continue
?用于循環體中
?continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;最內層為第1層
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
continue
fi
CMDn
…
done
例1:continue
#!/bin/bash
#
for i in {1..10};do
if [ $i -eq 5 ];then
continue
fi
echo $i
done
執行結果是:當$i=5時,
[root@centos6 data]#continue.sh
1
2
3
4
6
7
8
9
10
例2:continue2
#!/bin/bash
#
for i in {1..3};do
for j in {1..10};do
if [ $j -eq 5 ];then
continue 2
fi
echo $j
done
echo
done
執行結果為:
[root@centos6 data]#continue.sh
1
2
3
4
1
2
3
4
1
2
3
4
continue2 退出的是外層的for循環語句,外層循環的echo執行也被終端
八、循環控制語句break
用于循環體中
break [N]:提前結束第N層循環,最內層為第1層
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
break
fi
CMDn
…
done
例1:break
#!/bin/bash
#
for i in {1..3};do
for j in {1..10};do
if [ $j -eq 5 ];then
break
fi
echo $j
done
echo
done
執行結果為:
[root@centos6 data]#break.sh
1
2
3
4
1
2
3
4
1
2
3
4
此時break中斷的是內部循環
例2:break2
#!/bin/bash
#
for i in {1..3};do
for j in {1..10};do
if [ $j -eq 5 ];then
break 2
fi
echo $j
done
echo
done
執行結果為:
[root@centos6 data]#break.sh
1
2
3
4
此時break 2中斷的是外部循環
例3:猜數字,生成一個隨機數,提示輸入1到10以內的數字,然后比較大小,
#!/bin/bash
#
rand=$[RANDOM%11]
while read -p “please input a digit in 0 to 10: ” n;do
if? [[ ! “$n” =~ ^[0-9]+$ ]];then
echo “please in put a digit 1-10”
continue
fi
if [ “$n” -lt “$rand” ];then
echo “less”
elif [ “$n” -gt “$rand” ];then
echo “more”
else
echo “right”
break 2
fi
done
九、循環控制shift命令
shift [n]
用于將參量列表 list 左移指定次數,缺省為左移一次。
參量列表 list 一旦被移動,最左端的那個參數就從列表中刪除。while 循環遍歷位置參量列表時,常用到 shift
./doit.sh a b c d e f g h
./shfit.sh a b c d e f g h
例1:創建用戶,
#!/bin/bash
#
until [ -z “$1” ];do
useradd $1
echo “$1 has created”
shift 1
done
echo done
例2:打印所有的
#!/bin/bash
while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done
十、while特殊用法
while循環的特殊用法(遍歷文件的每一行):
while read line; do
循環體
done < /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
練
例1:文件/etc/passwd中uid為偶數的行,顯示其用戶名和id號
while read? line;do
id=`echo $line|cut -d: -f3 `
user=`echo $line|cut -d: -f1`
if [ $[id%2] -eq 0 ];then
echo “$user:$id”
fi
done </etc/passwd
例2:檢查分區利用率,利用率大于5報警,且顯示其設備名
#!/bin/bash
df | while read line;do
if echo $line | grep “^/dev/sd” &>/dev/null;then
used=`echo $line | sed -nr “s/.*[ ]+([0-9]{1,3})%.*/\1/p”`
device=`echo $line | cut -d” ” -f1`
if [ $used -gt 5 ];then
echo “$device will full,used $used%”
fi
fi
done
十一、for循環的特殊格式:
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))
do
循環體
done
例1:1到100的和
#!/bin/bash
#
for ((sum=0,i=1;i<=100;i++ ));do
sum=$[sum+i]
done
echo sum=$sum
十二、select循環與菜單
select variable in list
do
循環體命令
done
select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示 PS3 提示符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY 中
select與case
select 是個無限循環,因此要記住用 break 命令退出循環,或用 exit 命令終止腳本。也可以按 ctrl+c 退出循環
select 經常和 case 聯合使用
與 for 循環類似,可以省略 in list,此時使用位置參量
例1:
PS3=”please select scripts (1-4):”
select menu in etcbakup yum.sh alias.sh reset.sh;do
case $menu in
etcbakup)
echo “$REPLY:start bakup”
break
;;
yum.sh)
echo “$REPLY:start configuure yum”
break
;;
alias.sh)
echo “$REPLY:start configure alias”
break
;;
reset.sh)
echo “$REPLY:start reset the system environment”
break
;;
*)
echo “$REPLY:nothing to do”
;;
esac
done
十三、信號捕捉trap
trap ‘觸發指令’ 信號
自定義進程收到系統發出的指定信號后,將執行觸發指令,而不會執行原操作
trap ” 信號
忽略信號的操作
trap ‘-‘ 信號
恢復原信號的操作
trap -p
列出自定義信號操作
例1:捕捉信號2
trap “press the ctrl+c” 2???????????????????? ###使2信號失效,且提示press the ctrl+c
for (( i=0;i<=10;i++ ));do
echo $i
sleep 1
done
trap “” 2????????????????????????????????? ###使2信號失效,不提示
for (( i=11;i<=20;i++ ));do
echo $i
sleep 1
done
trap “-” 2
for (( i=21;i<=30;i++ ));do
echo $i
sleep 1
done
十四、定義函數
函數由兩部分組成:函數名和函數體
help function
語法一:
f_name (){
…函數體…
}
語法二:
function f_name {
…函數體…
}
語法三:
function f_name () {
…函數體…
}
十五、查看函數、刪除函數
declare -f 查看系統所有函數
declare -f function_name 查看函數
unset function_name 刪除函數
十六、函數中變量生效范圍
默認函數和當前shell的變量使通用的
[root@centos6 ~]#func1 () { name=wang;echo “func1:$name”; }
[root@centos6 ~]#func1
func1:wang
[root@centos6 ~]#echo $name
wang
讓函數中變量只在函數中生效加上local,如:func1 () { local name=wang;echo “func1:$name”; }
declare -i 在函數中聲明變量相當賦予了local的特性,只在函數中生效
[root@centos6 ~]#func2 () { declare -i num=100;echo “$num”; }
[root@centos6 ~]#func2
100
[root@centos6 ~]#echo $num
declare -ig 在函數中聲明變量的相當于普通變量,在函數和當前shell生效(在centos6上不支持,支持centos7)
[root@centos7 boot]#func1 () { declare -ig num=100;echo $num; }
[root@centos7 boot]#func1
100
[root@centos7 boot]#echo $num
100
十七、函數調用
例1:根據參數選擇
#!/bin/bash
green_yellow (){
if [ “$1” = “-r” ];then
echo -e “\e[1;43m \e[1;42m \e[0m\c”
else
echo -e “\e[1;42m \e[1;43m \e[0m\c”
fi
echo
}
green_yellow
green_yellow -r
例2:寫一個函數,顯示當前系統版本,如果是6則顯示oldversion,否則顯示最新版本
方法一
[root@centos7 boot]#version () {
> ver=`sed -r “s/.*[ ]+([0-9]+)\..*/\1/” /etc/centos-release`
> if [ $ver -eq 6 ];then
>???? echo “oldversion”
> else
>???? echo “newversion”
> fi
> echo $ver
> }
方法二
[root@centos7 boot]#version() { ver=`sed -r “s/.*[ ]+([0-9]+)\..*/\1/” /etc/centos-release`;echo “$ver”; }
[root@centos7 boot]#version
7
[root@centos7 boot]#if [ `version` -eq 6 ];then echo version is old;else echo version is new;fi
version is new
方法三:根據return返回值判斷
[root@centos7 boot]#version() { ver=`sed -r “s/.*[ ]+([0-9]+)\..*/\1/” /etc/centos-release`;return $ver; }
[root@centos7 boot]#version
[root@centos7 boot]#echo $?
7
[root@centos7 boot]#if [ `version` -eq 6 ];then echo version is old;else echo version is new;fi
version is new
十八、實現多個腳本調用一個函數
編輯一個文件,如functions,把寫好的函數都寫入文件。然后在別的腳本中調用
寫入腳本格式簡單如下:
#!/bin/bash
source /data/functions
函數1
函數2
………..
十九、action函數
[root@centos7 boot]#source /etc/init.d/functions
[root@centos7 boot]#action “command successd”
command successd?????????????????????????????????????????? [? OK? ]
[root@centos7 boot]#action “command failed” /bin/false
command failed???????????????????????????????????? ????????[FAILED]
二十、定義全局函數
全局函數在子shell生效,在腳本調用腳本時可用
[root@centos7 boot]#func1 () { local num=100;echo $num; }
[root@centos7 boot]#func1
100
[root@centos7 boot]#export -f func1
二十一、數組
變量:存儲單個元素的內存空間
數組:存儲多個元素的連續的內存空間,相當于多個變量的集合
數組名和索引
索引:編號從0開始,屬于數值索引
注意:索引可支持使用自定義的格式,而不僅是數值格式,即為關聯索引,bash4.0版本之后開始支持
bash的數組支持稀疏格式(索引不連續)
聲明數組:
declare -a ARRAY_NAME? 普通數組
declare -A ARRAY_NAME: 關聯數組 ?必須先聲明,后使用
注意:兩者不可相互轉換
二十二、數組元素的賦值:
(1) 一次只賦值一個元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]=”Sunday”
weekdays[4]=”Thursday”
(2) 一次賦值全部元素
ARRAY_NAME=(“VAL1” “VAL2” “VAL3″ …)
(3) 只賦值特定元素
ARRAY_NAME=([0]=”VAL1″ [3]=”VAL2” …)
(4) 交互式數組值對賦值
read -a ARRAY
1.一次只賦值一個元素
[root@centos6 data]#declare -a name[1]=a
[root@centos6 data]#declare -a name[2]=b
[root@centos6 data]#declare -a name[3]=c
顯示所有數組元素
[root@centos6 data]#echo ${name[*]}
a b c
2.一次賦值多個元素(可以生成列表)
例1:
[root@centos6 data]#declare -a name=(“c” “d” “e”)
[root@centos6 data]#echo ${name[*]}
c d e
例2:生成列表
[root@centos6 data]#number=({1..10})
[root@centos6 data]#echo ${number[*]}
1 2 3 4 5 6 7 8 9 10
例3:
[root@centos6 data]#filename=(/data/*.sh)
[root@centos6 data]#echo ${filename[@]}
/data/3.sh /data/67_createuser.sh /data/9×9.sh /data/a.sh /data/checkint.sh
3.賦值特定的元素
[root@centos6 data]#name=([1]=x [2]=y)
[root@centos6 data]#echo ${name[*]}
x y
4.交互式數組賦值
例1:
[root@centos6 data]#read -a name
wang li zhang zhao
[root@centos6 data]#echo ${name[*]}
wang li zhang zhao
顯示所有數組:
declare -a
引用數組
引用數組元素:
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標為0的元素
引用數組所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
數組的長度(數組中元素的個數):
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
刪除數組中的某元素:導致稀疏格式
unset ARRAY[INDEX]
刪除整個數組:
unset ARRAY
二十三、在已有的數組后面添加新元素
? 首先不知道哪些下標被占用,可以這樣定義declare -a name[${#name[*]}]=wang
${#name[*]}代表元素的個數
二十四、生成20個隨機數保存于數組中,并找出其最大值和最小值
#!/bin/bash
#
declare -a rand
for ((i=0;i<20;i++));do
rand[$i]=$RANDOM
if [ $i -eq 0 ];then
max=${rand[$i]}
min=${rand[$i]}
else
[ $max -lt ${rand[$i]} ] && max=${rand[$i]}
[ $min -gt ${rand[$i]} ] && min=${rand[$i]}
fi
done
echo ${rand[*]}
echo $max $min
二十五、數組賦值
#!/bin/bash
#
declare -A disk
df |grep ^/dev/sd |while read line;do
device=`echo $line|cut -d” ” -f1`
used=`echo $line |sed -r “s/.*[ ]([0-9]{1,3}).*/\1/”`
disk[$device]=$used
echo ${disk[$device]}
done
二十六、字符串切片
${#var}:返回字符串變量var的長度
例1:
[root@centos6 ~]#str=`echo {a..z}|tr -d ” “`
[root@centos6 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos6 ~]#echo ${#str}
26
${var:offset}:表示跳過幾個開始取值
例:跳過5個開始取值
[root@centos6 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos6 ~]#echo ${str:5}
fghijklmnopqrstuvwxyz
${var:offset:N }:表示跳過前幾個子浮窗,然后取N個子浮窗
例:
[root@centos6 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos6 ~]#echo ${str:3:4}
defg
${var: -offset}:表示取后面倒數幾個字符,注意-offset前面要加空格
例:
[root@centos6 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos6 ~]#echo ${str: -3}
xyz
${var:offset:-length}:從最左側跳過offset字符,一直向右取到距離最右側lengh個字符之前的內容(去頭去尾取中間)
例:
[root@centos7 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos7 ~]#echo ${str:3:-3}
defghijklmnopqrstuvw
例2:取后面4個,再去掉最后兩個
[root@centos7 ~]#echo $str
abcdefghijklmnopqrstuvwxyz
[root@centos7 ~]#echo ${str: -4:-2}
wx
命令matemp
創建隨機文件
[root@centos6 data]#mktemp? /data/tmpXXXX
/data/tmp4YEW
創建隨機目錄-d
[root@centos6 data]#mktemp -d /data/tmpXXXXX
/data/tmpq9VGE
-p指定生成文件后放置的目錄
[root@centos6 data]#mktemp -p /data/ tmpXXXXXXX
/data/tmpLCNalET
-p指定目錄可以用變量替代,執行的結果也可以放置到一個變量之中,方便以后查找刪除
tmpfile=`mktemp -p “$dir” tmpXXXX
rm -rf $tempfile
install命令:
install [OPTION]… [-T] SOURCE DEST 單文件
install [OPTION]… SOURCE… DIRECTORY
install [OPTION]… -t DIRECTORY SOURCE…
install [OPTION]… -d DIRECTORY…創建空目錄
選項:
-m MODE,默認755
-o OWNER
-g GROUP
示例:
install -m 700 -o wang -g admins srcfile desfile
install –m 770 –d /testdir/installdir
?????
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/98464