shell腳本進階

一、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

(0)
王琪鋒王琪鋒
上一篇 2018-05-13
下一篇 2018-05-14

相關推薦

  • RHCE考試筆記

    (2)下午RHCE部分

    Linux筆記 2018-07-14
  • 文件系統掛載

    一、mount、umount、mount -o remount、findmnt、lsof、fuser
    二、掛載設置ACL權限、模擬U盤功能、losetup
    三、UUID故障處理、分區遷移與恢復、永久掛載光盤分區、掛載USB、永久掛載文件夾
    四、SWAP、掛載光盤、制作ISO鏡像、制作Centos6Everthing
    五、df、du、dd備份/恢復/修復硬盤

    2018-05-26
  • 正則表達式 筆記

    重新復習的筆記

    2018-04-18
  • PXE自動化安裝centos6與centos7

    PXE自動化安裝centos7系統1、確保防火墻和selinux全部關閉2、yum -y install dhcp tftp-server httpd syslinux3、啟動相關服務systemctl start httpdsystemctl enable httpdsystemctl start tftp.servicesystemctl enable …

    Linux筆記 2018-05-28
  • 掛載點 文件通配符 目錄的一些理解

    掛載點 掛載點實際上就是linux中的磁盤文件系統的入口目錄,類似于windows中的用來訪問不同分區的C:、D:、E:等盤符。其實Windows也支持將一個磁盤分區掛在一個文件夾下面,只是我們用C:、D:這樣的盤符操作用慣了,一般沒有將分區掛到文件夾。文件一般掛載在misc文件夾下 在我們打開Centos 6(并未登錄)時在遠程控制臺是不能看到掛載點的如圖…

    2018-04-01
  • 重啟網卡失敗的解決方法

    重啟網卡 報Job for network.service failed because the control process exited with error code. See “systemctl status network.service” and “journalctl -xe” for details. 的錯誤

    2018-04-18
欧美性久久久久