RHCE8 资料整理
第 22 章 用bash写脚本
22.1 通配符
详细参考 https://blog.csdn.net/u010230019/article/details/132038691
通配符一般在shell语言中,常见元字符如下:
[]
:匹配一个字符,匹配的是出现在中括号中的字符[abc]
:匹配abc其中任意一
个字符[a-z]
:匹配a到z中的任意一
个子符[0-9
:匹配一个数字[a\-z]
:这里的\
表示转义,匹配a,-,z
其中任意一个字符[^a-z]
:除了a-z之外的字符?
:表示任意一个字符,这里是一
个,但不能匹配隐藏文件的点(.
)*
:表示任意多个字符,可以是0个,也可以是1个或者多个,但不能匹配隐藏文件的点(.
)
例如:
[root@node-138 ~]# ll|grep no[h]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[hdf]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[a-z]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[0-9]up.out
[root@node-138 ~]# ll|grep no[0\h9]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[!h-z]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[^h-z]up.out
[root@node-138 ~]# ll|grep no[^h]up.out
[root@node-138 ~]# ll|grep no?up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no*up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[d-i]up.out
-rw-------. 1 root root 1186 Aug 15 16:01 nohup.out
[root@node-138 ~]# ll|grep no[i-d]up.out
grep: Invalid range end
这里的-
必须是ascii码中的区间范围,如最后一个示例,如果倒序则不支持
22.2 变量
变量,指可以变的值
22.2.1 本地变量
格式:变量名=值
,需要注意:
- 变量名可以包括数字、字母和
_
,不能以数字开头,这个同C的规则 =
两边不能有空格值
如果包含空格,则需要由单引号或者双引号引起来- 定义变量的时候,不需要加
$
,引用时需要 - 本地变量只能影响当前shell,不能影响子shell
[root@node-138 ~]# a=100
[root@node-138 ~]# bash
[root@node-138 ~]# echo $a
[root@node-138 ~]# exit
exit
[root@node-138 ~]# echo $a
100
定义变量的两种方法:
- 把一个值或者命令的结果赋值给一个变量,这个命令需要用
$()
或者反引号``括起来 - 通过
read
命令获取变量
[root@node-138 ~]# ip=`ifconfig ens37|awk '/inet /{print $2}'`
[root@node-138 ~]# echo $ip
192.168.17.138
[root@node-138 ~]# ip=`ifconfig ens37|awk 'NR==2 {print $2}'`
[root@node-138 ~]# echo $ip
192.168.17.138
[root@node-138 ~]# read -p "input" aa
input100
[root@node-138 ~]# echo $aa
100
22.2.2 环境变量
定义环境变量和本地变量类似,不过需要加export
环境变量可以影响子shell
[root@node-138 ~]# export a=110
[root@node-138 ~]# bash
[root@node-138 ~]# echo $a
110
[root@node-138 ~]# exit
exit
[root@node-138 ~]# echo $a
110
[root@node-138 ~]# env |grep a
...
a=110
...
22.2.3 位置变量和预定义变量
$0
:表示脚本名称$1
:表示第一个参数$2
:表示第二个参数${10}
:第十个参数$#
:参数个数$*
:代表『 “$1c$2c$3c$4” 』,其中 c 为分隔字符,默认为空格键, 所以本例中代表『 “$1 $2 $3 $4” 』之意。一个字符串$@
:代表『 “$1” “$2” “$3” “$4” 』之意,每个变量是独立的(用双引号括起来);多个字符串
单引号和双引号区别:
[root@server ~]# xx=tom
[root@server ~]# echo "my name is $xx"
my name is tom
[root@server ~]# echo 'my name is $xx'
my name is $xx
单引号无法解析变量
22.3 返回值
linux中,命令正确执行,返回值为0
。如果没有正确执行,则返回非0
。返回值记录在$?
中
- 返回值为非0,不一定是语法错误,执行结果如果有
否定
的意思,返回值也为非0。
[root@server ~]# ping 192.168.17.138
PING 192.168.17.138 (192.168.17.138) 56(84) bytes of data.
64 bytes from 192.168.17.138: icmp_seq=1 ttl=64 time=0.311 ms
64 bytes from 192.168.17.138: icmp_seq=2 ttl=64 time=0.282 ms
^C
--- 192.168.17.138 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1042ms
rtt min/avg/max/mdev = 0.282/0.296/0.311/0.014 ms
[root@server ~]# echo $?
0
[root@server ~]# ping 121.147.143.14
PING 121.147.143.14 (121.147.143.14) 56(84) bytes of data.
^C
--- 121.147.143.14 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3056ms
[root@server ~]# echo $? #命令正确执行,但返回值为非0
1
[root@server ~]# grep rootxx /etc/passwd
[root@server ~]# echo $? #命令正确执行,但返回值为非0
1
[root@server ~]# xxx
bash: xxx: command not found...
Failed to search for file: /mnt/AppStream was not found
[root@server ~]# echo $? #命令不能正确执行,但返回值为非0
127
如果命令未能如预期成功执行
,则一般都是返回值非0
22.4 数值运算
常用的数学运算符,如:
+
:加-
:减*
:乘/
:除**
:幂
进行数学运算的表达式有$(())、$[]、let
等,命令如下:
[root@server ~]# echo 2*3
2*3
[root@server ~]# echo $((2*3))
6
[root@server ~]# echo $((2**3))
8
[root@server ~]# echo $[2*3]
6
$(())
和$[]
用法一样,let
如下
[root@server ~]# let a=2*3
[root@server ~]# echo $a
6
也可以通过declare -i
把变量定义为整数,再进行运算
[root@server ~]# declare -i b
[root@server ~]# b=2*3
[root@server ~]# echo $b
6
前面的表达式无法计算浮点数,计算浮点数需要使用bc
,格式
echo "[scale=N;]算法"|bc [-l]
scale 指定小数点后面保留位数
-l 定义使用的标准数学库;
例如
[root@server ~]# echo "3/2"|bc
1
[root@server ~]# echo "scale=3;3/2"|bc
1.500
[root@server ~]# echo "3/2"|bc -l
1.50000000000000000000
22.5 比较、对比和判断
详细参考
https://blog.csdn.net/u010230019/article/details/132186768
https://blog.csdn.net/u010230019/article/details/131239700
22.6 if判断语句
# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况执行
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ]; then
当条件判断式二成立时,可以进行的指令工作内容;
else
当条件判断式一与二均不成立时,可以进行的指令工作内容;
fi
[root@server ~]# if [ $UID -eq 0 ];then
> echo "root"
> fi
root
22.7 for循环语句
参考 https://blog.csdn.net/u010230019/article/details/132193766
shell支持两种形式的for语句,一种是shell形式,另一种是C形式
for var in con1 con2 con3 ...
do
程序段
done
for (( 初始值; 限制值; 执行步阶 ))
do
程序段
done
[root@server ~]# for ((i=1;i<10;i++));do
> echo $i
> done
1
2
3
4
5
6
7
8
9
22.8 while循环语句
while [ condition ] <==中括号内的状态就是判断式
do <==do 是循环的开始!
程序段落
done <==done 是循环的结束
[root@server ~]# cat cc.sh
#!/bin/bash
declare -i n=1
while [ $n -lt 10 ];do
echo $n
let n=$n+1
done
[root@server ~]# ./cc.sh
1
2
3
4
5
6
7
8
9
从文件输入内容进行循环:
while read aa;do
echo $aa
done < file
[root@server ~]# while read aa;do echo $aa; done < 123
1
2
3
[root@server ~]# cat 123
1
2
3
死
循环:
while ((1));do
或
while true;do
或
while :;do
命令
done
while true;do
systemctl is-active vsftpd &> /dev/null
if [ $? -ne 0 ];then
systemctl start vsftpd
fi
sleep 1
done