shell脚本应用及循环语句

分类:shell编程 阅读:6360 次

Shell脚本应用及循环语句

一.bash通配符:

1.?//任意的单个字符

2.*//0个或多个字符

3.[] //区间内的任意一个字符

4.; //分割命令,忽略前一个命令的执行结果,继续执行后面的命令

5.& //后台执行程序

6.&& //前面的命令执行成功,返回值是0,执行后面的命令。

7.|| //前面的命令执行失败,返回值非0,执行后面的命令。

8.| //管道

9.() //开启子shell,执行里面的命令

10.{} //里面的命令在当前shell执行

11.> >> //输出重定向

12.< << //输入重定向

13.$ //定义变量

14.\ //转义;命令的折行

15.`` //调用命令的执行结果;不可以嵌套

16.- //连字符;命令的选项的前导, - --

17.''//强引用符号;屏蔽特殊字符

18."" //弱引用符号;`` $ \这3个符号屏蔽不了

19.://表示空操作,返回值永远是0;while循环

20.[:alnum:]//字母+数字

21[:alpha:]//字母

22[:lower:]//小写字母

23[:upper:]//大写字母

24[:digit:]//十进制数

25[:punct:]//符号

26[:space:]//空白字符(空格“tab”)

27[[:alnum:]]//任意的一个字母或数字[a-Z0-9]

28[^[:alnum:]]//取反

[[:alnum:]!]

二.变量

1.注意

(1)=的两边千万不要有空格

(2)不要使用$作为变量的名字

(3)变量名的长度--256个字符,区分大小写

2.如何引用

(1)直接引用:

echo 命令

-e:启用\(反斜线)控制字符(\t \n)的转换

-n:取消换行符

[root@tx1 ~]# echo "123\t234"

123\t234

[root@tx1 ~]# echo -e "123\t234"

123 234

[root@tx1 ~]# echo -e "123\n234"

123

234

[root@tx1 ~]# echo -n "123\t234"

123\t234[root@tx1 ~]#

(2)间接引用

[root@tx1 ~]# a=b

[root@tx1 ~]# b=c

[root@tx1 ~]# echo $a

b

[root@tx1 ~]# echo ${!a}

c

(3)变量的作用域

@1在当前的shell里,定义的变量叫做本地变量-局部变量。

@2全局变量-环境变量,export把局部变量变成全局变量。只作用于子shell。

[root@tx1 ~]# x=123

[root@tx1 ~]# echo $x

123

[root@tx1 ~]# bash

[root@tx1 ~]# echo $x


[root@tx1 ~]# exit

exit

[root@tx1 ~]# export x

[root@tx1 ~]# bash

[root@tx1 ~]# echo $x

123


(4)查看定义的变量

@1.set查看所有的变量

@2.env查看全局变量

@3.unset取消变量unset+变量名

@4.设置变量为只读:readonly+变量名


(5)位置参数$

注:位置参数,从命令行传递给脚本,或者是传递给函数.或者赋职给一个变量.

$0命令本身

$1 $2 ...... ${10}

$#参数的个数

$*所有的参数


$@所有的参数(需要被” ”引用)

$$上一条命令的进程号

$?上一条命令的返回结果

$_上一条命令的最后一个参数

$!最后一个进入后台的命令的进程号

$()等同于``

$(())等同于$[]做数学运算的,但是只能算整数

(6)变量的置换

注:用来执行匹配或者是判断变量是否存在。

@1.${变量名:-字符串}:如果变量是空的,那么就返回字符串;否则返回变量的值

@2.${变量名:+字符串}:如果变量有值,那么使用字符串替换变量;否则返回空值

@3.${变量名:=字符串}:如果变量没有值,那么就把字符串赋值给变量;否则返回变量的值


@4.${变量名:?提示信息}:如果变量没有值,那么返回提示信息

@1.

[root@tx1 ~]# echo $a

[root@tx1 ~]# echo ${a:-123}

123

[root@tx1 ~]# b=abc

[root@tx1 ~]# echo ${b:-123}

Abc


@2.

[root@tx1 ~]# echo ${a:+123}

[root@tx1 ~]# echo ${b:+123}

123


@3.

[root@tx1 ~]# echo $a

[root@tx1 ~]# echo $b

abc

[root@tx1 ~]# echo ${a:=123}

123

[root@tx1 ~]# echo $a

123

[root@tx1 ~]# echo ${b:=123}

abc

[root@tx1 ~]# echo $b

Abc


@4.

[root@tx1 ~]# unset a

[root@tx1 ~]# echo ${a:?}

bash: a: parameter null or not set

[root@tx1 ~]# echo ${a:?没有设置变量}

bash: a:没有设置变量

(7)变量的匹配模式

#:从变量的值的头部开始最小匹配,然后删除

##:从变量的值的头部开始最大匹配,然后删除

% :从变量的值的尾部开始最小匹配,然后删除

%%:从变量的值的尾部开始最大匹配,然后删除

:num1:num2:截取变量的值,num1是开始的位置,num2是截取出来几位;0是第一个字符

@1.

[root@tx1 ~]# echo ${pth#*/}

usr/bin/local/bin/all

[root@tx1 ~]# echo ${pth##*/}

all

@2.

[root@tx1 ~]# echo ${pth%/*}

/usr/bin/local/bin

[root@tx1 ~]# echo ${pth%%/*}


[root@tx1 ~]#

@3.

[root@tx1 ~]# echo ${pth:0:6}

/usr/b

[root@tx1 ~]# echo ${pth:3:6}

r/bin/

三.If语句

1.单分支if语句.

if [条件表达式]; then

命令;...

fi

注:条件满足的时候,就会运行then后面的语句,不满足就直接退出判断语句


2.双分支if语句

if [条件表达式];then

命令;...

else

命令;...

fi

注:等条件满足的时候就会运行then后面的语句,条件不满足的时候就运行else后面的语句。

3.条件表达式(man test)

(1)字符串的判断

str1 = str2检查str1与str2是否相同

str1 != str2检查str1与str2是否不同

str1 < str2检查str1是否小于str2

str1 > str2检查str1是否大于str2

-n str1 检查str1的长度是否大于0

-z str1 检查str1的长度是否为0

=~:判断左边的字符串是否能够被右边的模式所匹配,[[ "$opt1" =~ pattern ]], 注:判断字符串的时候,字符串要用""包起来(更详细的man test)


(2)整数的判断

-eq等于

-ge大于等于

-gt 大于

-le小于等于

-lt 小于

-ne不等于

(3)文件的判断

-b file 判断是否存在且为块文件

-c file判断是否存在且为字符文件

-d file判断是否存在且为目录文件

-e file 判断文件是否存在

-f file 判断文件是否存在且为一个普通文件

-h file判断是否存在且为符号链接

-r file判断是否存在且可读

-s file判断是否存在且不为空

-w file判断是否存在且可写

-x file 判断是否存在且可执行

-O file判断是否存在且用户为当前用户

-G file判断是否存在且组为当前组


(4)条件语句

与-a

if [表达式1 -a表达式2 ]


或-o

if [表达式1 -o表达式2 ]


非!

if [ !表达式]

[[表达式1 &&表达式2 ]] ==-a

[[表达式1 ||表达式2 ]] ==-o

[[ !表达式]] ==!

if表达式

then

command

elif表达式

then

command

elif表达式

then

command

......

else

command

fi


(5)多重判断


例1.

注:read -p

-t 超时时间 -t 3(秒)

-s 输入没有回显,(密码)

[root@tx1 ~]# vim tx1.sh

#!/bin/bash

#这是一个判断文件类型的脚本

if [ -b /dev/hda1 ]

then

echo "块设备"

fi


if [ -d /etc ]

then

echo "目录"

fi

if [ -e /etc/passwd ]

then

echo "普通文件"


fi

[root@tx1 ~]# ./tx1.sh

块设备

目录

普通文件

例2

#!/bin/bash

#这是一个判断用户是否存在的脚本


read -p "请输入一个用户名:" uname

if [ "$uname" = "" ]

then

echo "error"

else

ifgrep "^\<$uname\>" /etc/passwd &> /dev/null

then

echo "这个用户存在"

else

echo "这个用户不存在"

fi

fi

例3(if的嵌套)

注:为终端加密

[root@tx1 ~]# vim /etc/bashrc

read -p "请输入用户名:" uname

if [ "$uname" = "root" ]

then

read -p "请输入密码:" pass

if [ "$pass" = "123" ]

then

echo "welcome root"

else

exit 1

fi

else

exit 2

fi

打开一个新的终端后

请输入用户名:root

请输入密码:123

welcome root

[root@tx1 ~]#

例4

#!/bin/bash

#使用双重条件判断用户名和密码

read -t 5 -p "username: " uname

read -s -p "password: " pass

echo


if [ "$uname" = "root" -a "$pass" = "123" ]

then

echo "welcome root"

else

echo "go out"

fi

例5

#!/bin/bash

#判断一个用户的类型

read -p "请输入一个用户名:" uname

id=`grep "^\<$uname\>" /etc/passwd | cut -d : -f 3 `

if [ "$uname" = "" ]

then

echo "error"

elif [ $id -ge 500 ]

then

echo "$uname是普通用户"

elif [ $id -lt 500 -a $id -ge 1 ]

then

echo "$uname是系统用户"

else

echo "$uname是超级用户"

fi

[root@tx1 ~]# ./tx5.sh

请输入一个用户名:root

root是超级用户

[root@tx1 ~]# ./tx5.sh

请输入一个用户名:tx

tx是普通用户

[root@tx1 ~]# ./tx5.sh

请输入一个用户名:bin

bin是系统用户

[root@tx1 ~]# ./tx5.sh

请输入一个用户名:

error

四.case多分支判断

语法:

case $变量in

value1)

commands

;;

value2)

commands

;;

......

*)

commands

;;

esac

例1.

注:例如人的年龄:0婴儿,1-9幼儿,1-19少年,20-29青年,30-39中年,40-老年

#!/bin/bash

#判断人的年龄段

read -p "请输入一个人的年龄:" age

case $age in

0)

echo "婴儿"

;;

[1-9])

echo "幼儿"

;;

1[0-9])

echo "少年"

;;

2[0-9])

echo "青年"

;;

3[0-9])

echo "中年"

;;

*)

echo "老年"

;;

esac

[root@tx1 ~]# ./t1.sh

请输入一个人的年龄:3

幼儿

[root@tx1 ~]# ./t1.sh

请输入一个人的年龄:67

老年

[root@tx1 ~]# ./t1.sh

请输入一个人的年龄:20

青年


五.For循环

注:for循环 事先提供一个元素列表,而后,使用变量去遍历此元素列表,每访问一个元素,就执行一次循环体,直到元素访问完毕
1.语法:

for变量in变量列表

do

commands

done

例1.用for循环输出三个数

#!/bin/bash

for i in "$*"

do

echo $i

done


for j in "$@"

do

echo $j

done

[root@tx1 ~]# ./t3.sh 1 2 3

1 2 3

1

2

3

例2.把/usr/share/doc/下所有的index.html复制到/tmp/index/目录下,/tmp/index/ 不确定是否存在。

#!/bin/bash

if [ -d /tmp/index ]

then

num=1

for i in $(find /usr/share/doc -name index.html)

do

/bin/cp $i /tmp/index/index.html.$num

num=$(($num+1))

done

else

mkdir /tmp/index

num=1

for i in $(find /usr/share/doc -name index.html)

do

/bin/cp $i /tmp/index/index.html.$num

num=$(($num+1))

done

fi

六.While语句

语法:

while [表达式]

do

commands

更新表达式

done


表达式的作用:判定循环是否执行。

表达式的返回值为真,$?=0,执行命令

表达式的返回值是假的,结束循环。

:;true 返回值永远是真的。

例1.批量创建5个用户

[root@tx1 ~]#catt1.txt

tx1

tx2

tx3

tx4

tx5

[root@tx1 ~]#cat t6.sh

#!/bin/bash

while read line

do

uname=`echo $line`

useradd $uname

echo $uname | passwd $uname --stdin

done < /root/t1.txt

例2.信号捕捉

注:信号捕捉,trap,1 2 9 15,信号9是捕捉不了的。

#!/bin/bash

#信号捕捉


trap "echo进程还在继续" 1


while :

do

echo "hello"

sleep 3

done

[root@tx1 ~]# ps -a

PID TTY TIME CMD

18810 pts/2 00:00:00 bash

18813 pts/2 00:00:00 sleep

18814 pts/1 00:00:00 ps

[root@tx1 ~]# kill -1 18810


[root@tx1 ~]# ./t7.sh

hello

hello

hello

hello

进程还在继续

hello

七.Until语句

语法:

until [表达式]

do

commands

更新表达式

done


表达式的作用:判定循环是否执行。

表达式的返回值为假的时候,执行循环,$?非0

表达式的返回值为真的时候,结束循环

例1.

#!/bin/sh


a=10;

until [[ $a -lt 0 ]];do

echo $a;

((a--));

done;

[root@tx1 ~]# ./t8.sh

10

9

8

7

6

5

4

3

2

1

0

八.shift,break和continue

例1

#!/bin/bash

until [ $# -eq 0 ]

do

echo $*

shift

done

[root@tx1 ~]# ./tt1.sh 1 2 3 4 5 6

1 2 3 4 5 6

2 3 4 5 6

3 4 5 6

4 5 6

5 6

6

例2.break跳出循环

#!/bin/bash

for i in `seq 1 2`

do

for j in `seq 1 3`

do

echo $j

if [ $j -eq 2 ]

then

break #跳出当前循环

fi

done

done

[root@tx1 ~]# ./tt2.sh

1

2

1

2


例3

#!/bin/bash

for i in `seq 1 10`

do

for j in `seq 1 3`

do

echo $j

if [ $j -eq 2 ]

then

break 2 #跳出第2层循环

fi

done

done

[root@tx1 ~]# ./tt3.sh

1

2

例4(continue结束本次循环)

#!/bin/bash

for i in `seq 13`

do

for j in `seq 1 3`

do

if [ $j -eq 2 ]

then

continue #结束本次循环

fi

echo $j

done

done

[root@tx1 ~]# ./tt4.sh

1

3

1

3

1

3

例5

#!/bin/bash

for i in `seq 13`

do

for j in `seq 1 3`

do

if [ $j -eq 2 ]

then

continue 2 #结束第2层的本次循环

fi

echo $j

done

done


[root@tx1 ~]# ./tt5.sh

1

1

1