Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
特殊变量列表
变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。一般情况下,大部分命令执行成功会返回 0,失败返回 1。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
$* 和 $@ 的区别
$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" “)包含时,都以”$1" “
2
"
…
"
2" … "
2"…"n” 的形式输出所有参数。
但是当它们被双引号(" “)包含时,”$*" 会将所有的参数作为一个整体,以"$1 $2 …
n
"
的
形
式
输
出
所
有
参
数
;
"
n"的形式输出所有参数;"
n"的形式输出所有参数;"@" 会将各个参数分开,以"$1" “
2
"
…
"
2" … "
2"…"n” 的形式输出所有参数。
下面的例子可以清楚的看到 $* 和 $@ 的区别:
#!/bin/bash
echo “$=" $
echo “”$"=" "$”
echo “$@=” $@
echo “”$@"=" “$@”
echo “print each param from $"
for var in
∗
d
o
e
c
h
o
"
* do echo "
∗doecho"var"
done
echo “print each param from $@”
for var in
@
d
o
e
c
h
o
"
@ do echo "
@doecho"var"
done
echo "print each param from "$”"
for var in “
∗
"
d
o
e
c
h
o
"
*" do echo "
∗"doecho"var”
done
echo “print each param from “$@””
for var in “
@
"
d
o
e
c
h
o
"
@" do echo "
@"doecho"var”
done
执行 ./test.sh “a” “b” “c” “d”,看到下面的结果:
∗
=
a
b
c
d
"
*= a b c d "
∗=abcd"“= a b c d
@
=
a
b
c
d
"
@= a b c d "
@=abcd"@”= a b c d
print each param from $
a
b
c
d
print each param from
@
a
b
c
d
p
r
i
n
t
e
a
c
h
p
a
r
a
m
f
r
o
m
"
@ a b c d print each param from "
@abcdprinteachparamfrom""
a b c d
print each param from "
@
"
a
b
c
d
说
明
:
双
引
号
包
含
时
,
"
@" a b c d 说明:双引号包含时,"
@"abcd说明:双引号包含时,"“的参数被当做一个整体,而”$@"还是遍历每一个参数
num=10
num+=1 将左边的值加上右边的值再把结果赋值给左边的变量 num=num+1
[root@localhost opt]# n=10
[root@localhost opt]# let n+=1
[root@localhost opt]# echo $n
11
格式化输出:
echo 默认是将"字符"输出到标准输出–终端
-e 解释转移字符
\n 回车符
\t 制表符
\b 删除键 backspace/delete
-n 忽略换行符
[root@localhost opt]# echo abc
abc
[root@localhost opt]# echo -n “abc”
abc[root@localhost opt]#
格式化输入:
read 读区用户输入并复制给变量
-p 忽略换行符,
-n 接受输入的字符数量
-t 定义输入超时时间
-s 关闭 回显
shell_day3
case语句:
情况。
语法:
case “$1” in
情况1)
command
;;
情况2)
command
;;
情况3)
command
;;
*)
command
;;
esac
如果传递给脚本的第一个参数,匹配上"情况1",那么执行"情况1"中的命令;
for循环
基本语法:
for i in {1…20}
do
command
command
done
i:变量名,他的值来自{}中。第一次循环时,i的值是1,第二次循环时,i的值是2,变量i依次被{}中的值赋值
do ...done: 表示do和done之间的代码。叫循环体--定义循环时要做的工作(要执行的代码)
循环什么时候结束:当{}中的值依次赋予i并执行完循环体中的代码后,整个循环结束。
for i in 1 2 3 4 5 6 7 //用列表去赋值i
for i in `cat /etc/passwd` //将命令执行的结果赋值给变量,i的值以换行符来分割
for i in `seq 9 -2 1` //步进为2
类C语言for循环语法:
for ((i=1;i<=9;i++))
i=1 表示设置的变量i的初始值
i++ 表示变量i值的调整,每次加1。i++表示先拿着i的值去循环,本次循环结束后,在调整i的值(+1)
i<=9 表示循环的条件,当条件判断为真,那么循环;否则,退出循环。
i++ i++表示先拿着i的值去干活,再调整i的值(+1 )
++i 先调整i的值,再去干活
[root@localhost day3]# echo $i
2
[root@localhost day3]# let var=i++
[root@localhost day3]# echo $var
2
[root@localhost day3]# echo $i
3
[root@localhost day3]# i=1
[root@localhost day3]# let var=++i
[root@localhost day3]# echo $var
2
[root@localhost day3]# echo $i
2
嵌套:
for循环中嵌套if
循环嵌套循环–外循环循环一次,内循环循环一轮
循环控制语句:
break 打破;当执行到这条语句时,打破循环,即终止(退出)循环。
continue 继续;–>跳过。跳过某次循环过程中,从该语句到done之间的语句,并继续下一次循环。
练习:测试192.168.18.0/24网段主机存活情况(能ping通即认为主机存活)
[root@master lnmp]# cat ping.sh
#!/bin/bash
for ((i=1;i<255;i++))
do
ping -c 1 10.80.2.$i
if [ $? -eq 0 ];then
echo 10.80.2.$i >> ./ping.txt
else
echo 10.80.2.$i > /dev/null
fi
done
九九乘法表:
RANDOM 0~65535
IFS -->internal field separator
内部 字段 分隔符
作业:
1、脚本运行后,读取用户输入的一个数字并赋值给n,然后脚本做判断:
如果这个数字大于100或者低于0,输出"Unkown Error!",退出脚本,设置脚本退出状态码为3
如果这个数字大于95且小于等于100,输出"Critical: 情况紧急,内存剩余(100-n)%",设置脚本退出状态码为2
如果这个数字大于80且小于等于95,输出"Warnning: 警告,内存剩余(100-n)%",设置脚本退出状态码为1
如果这个数字小于等于80,输出"Memory OK!",设置脚本退出状态码为0
2、用户输入一个年份,程序来判断该年份是平年还是闰年,用户可以连续输入年份,直到输入的年份为quit时退出程序
注:闰年:能被4整除且不能被100整除或能直接被400整除的年份为闰年
3、假设用户通过输入密码进入手机:要求本程序实现:
用户可以有三次密码输入不正确的机会,如果密码输入失败次数如果超过3次,锁屏,锁屏时间为失败次数乘以2秒
[root@master lnmp]# cat passwd.sh
#!/bin/bash
passwd=1988
for ((i=1;i++;i<999))
do
read -p "请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:" pass
if [ $pass == $passwd ];then
echo "ok"
break
else
if [ $i -lt 4 ];then
continue
else
echo "密码错误,请等待$((($i-3)*2))秒后在输入密码"
sleep $((($i-3)*2))
fi
fi
done
[root@master lnmp]# ./passwd.sh
请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:4
请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:5
请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:6
密码错误,请等待2秒后在输入密码
请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:4
密码错误,请等待4秒后在输入密码
3^H请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:4
密码错误,请等待6秒后在输入密码
请输入密码,如果错误次数超过三次将被锁定2倍次数的时间,单位为秒:1988
ok
[root@master lnmp]#
4、写一个脚本,实现批量添加20个用户,用户名为user1-20,密码为用户名后面跟5个随机字符 user1xxx3e
[root@localhost day1]# cat /dev/urandom |head -1 |md5sum | head -c 5
5、写一款数字游戏
这是一支交互程序,程序运行后,会产生一个1~100之间的随机数。
让用户去猜这个数,如果用户猜的数大于该随机数了,告知其大了;
否则,告知其小了;
猜对了后输出“恭喜你猜对了,共猜xx次”
6、以/etc/passwd文件为处理文件,输出对应每个用户的用户名和其shell类型:
例:
root's shell is /bin/bash
bin's shell is /sbin/nologin
shell_day2
比较运算:
数值比较:
> -gt
< -lt
>= -ge
<= -le
= -eq
!= -ne
[root@localhost ~]# test 10 -le 2
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 0 -ne 0 ]
[root@localhost ~]# echo $?
1
字符串比较:
-n string 判断字符串长度非0
-z string 判断字符串长度为0
= 判断字符串相等
!= 判断字符串不相等
[root@localhost ~]# [ -z "" ] 改表达式表达的意思是:判断字符串长度为0,因为是空字符串(长度的确为0),故判断结果为真,返回值为0
[root@localhost ~]# echo $?
0
逻辑比较:
逻辑与 && //多个条件都满足,整体表达式判断结果为真
[root@localhost ~]# [ 0 -eq 0 ] && [ "abc" = "abc" ] //真真为真
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 0 -eq 0 ] && [ "abc" = "bc" ] //真假为假
[root@localhost ~]# echo $?
1
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# [ 0 -ne 0 ] && [ "abc" = "bc" ] //假假为假
[root@localhost ~]# echo $?
1
另外一种逻辑与的写法:
[root@localhost ~]# [ 10 -gt 5 -a "abc" = "abc" ]
[root@localhost ~]# echo $?
0
逻辑或 || -o
[root@localhost ~]# [ 0 -eq 0 ] || [ "abc" = "abc" ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 0 -lt 0 ] || [ "abc" = "abc" ]
[root@localhost ~]# echo $?
0
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# [ 0 -lt 0 ] || [ "abc" != "abc" ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 10 -gt 5 -o "abc" = "abc" ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 10 -gt 5 -o "abc" != "abc" ]
[root@localhost ~]# echo $?
0
逻辑非 ! 非,表示否定。真-->假 假-->真
文件比较:
stat filename //查看文件的详细信息,包括三个时间
-f file //判断文件存在并且是一个普通文件
-e file //判断文件存在
-d file //判断文件存在并且是一个目录
-x file //判断文件存在并且有执行权限
[root@localhost html]# [ -f first.sh ]
[root@localhost html]# echo $?
0
[root@localhost html]# [ ! -f test.sh ]
[root@localhost html]# echo $?
1
[root@localhost html]# [ -f /opt/a.txt ] || touch a.txt //实现:如果/opt没有a.txt,创建上;如果有,不执行touch命令
if判断语句:
语法一:
if [ 条件 ];then
command
command
fi
如果(if) 条件判断为真(条件成立–返回值为0);那么(then)执行command(命令),fi表示结束
语法二:
if [ 条件 ];then
command
command
else
command
fi
注:else 单词是“否则”的意思。这里表示“条件判断不为真”的情况。
脚本运行后,让用户输入一个分数,如果输入的分数大于等于60,脚本输出你通过了考试;如果低于60,输出不及格!
脚本运行后,让用户输入两个数字,脚本分别将他们赋值给a和b,如果a>b,脚本输出"a大于b";否则输出"a小于等于b"
语法三: 多条件判断
if [ 条件 ];then
command
elif [ 条件 ];then
command
elif [ 条件 ];then
command
else
command
fi
elif: else if 其他情况,其他条件
脚本运行后,让用户输入他的年龄;
如果用户输入的年龄大于120,或者小于0,脚本输出"GUN";
如果用户输入的年龄大于60,且小于120,脚本输出"大爷,你好!"
如果用户输入的年龄大于45,且小于等于60,脚本输出"叔叔,你好!"
如果用户输入的年龄大于30,且小于45,脚本输出"老男孩,你好!"
其他情况,输出"小屁孩,你好!"
telnet通过传参的方式测试服务的运行情况:
if语句其他写法:
if ( ping -c1 192.168.18.252 &>/dev/null );then
echo “The host is UP”
else
echo “The host is DOWN”
fi
case语句: