shell脚本应用及循环语句,shell脚本语句7.|| //前面
shell脚本应用及循环语句,shell脚本语句7.|| //前面
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 "123t234"
123t234
[root@tx1 ~]# echo -e "123t234"
123 234
[root@tx1 ~]# echo -e "123n234"
123
234
[root@tx1 ~]# echo -n "123t234"
123t234[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
八.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
评论暂时关闭