7月26日学习笔记 shell脚本,sed流式编译器

一、shell 基础

1shell 概念

   shell 英文翻译过来是外壳的意思,作为计算机语言来理解可以认为它是
操作系统的外壳。可以通过 shell 命令来操作和控制操作系统,比如
Linux 中的 shell 命令就包括 ls cd pwd 等等。
    shell 在内核的基础上编写的一个应用程序,它连接了用户和 Linux
核,从而让用户能够更加便捷、高效、安全的使用 linux 内核,这其实
就是 shell 的本质。
     使用专业术语的说法来解释, Shell 其实是一个命令解释器,它通过接
受用户输入的 Shell 命令来启动、暂停、停止程序的运行或对计算机进
行控制。
常见的 shell
Bourne Shell (/usr/bin/sh /bin/sh)
Bourne Again Shell (/bin/bash)
C Shell (/usr/bin/csh)
K Shell (/usr/bin/ksh)
Shell for Root (/sbin/sh)

2shell 脚本

shell 脚本就是由 Shell 命令组成的执行文件,将一些命令整合到一个文件
中,进行处理业务逻辑,脚本不用编译即可运行,它从一定程度上减轻
了工作量,提高了工作效率,还可以批量、定时处理主机,方便管理员
进行设置或者管理。

3shell 脚本编写注意事项

shell 命名 : shell 脚本名称命名一般为英文、大写、小写、后缀以 .sh 结尾

不能使用特殊符号、空格

名称要写的一眼可以看出功能,也就是顾名思义
shell脚本首行需要#!/bin/bash开头
shell脚本变量不能以数字、特殊符号开头,可以使用下划线 _,但不能
用破折号——

二、shell 脚本的构成

脚本声明
注释信息
可执行语句

三、编写 shell 脚本

1、伟大编程项目——Hello World

'Hello,World!' 中文意思是 你好,世界 。因为 The C Programming
Language 中使用它做为第一个演示程序,后来的程序员在学习编程或
进行设备调试时延续了这一习惯。
执行 shell 脚本的几种
bash 脚本名称
source 脚本名
在当前环境生效,其他方法都是在开一个
shell 进程
sh 脚本名称
添加 x 权限, ./ 脚本名称
shell 脚本其实就是有序执行命令条件
[root@localhost ~]# touch hello.sh
[root@localhost ~]# vim hello.sh
#!/bin/bash
echo "Hello World!" # 输出“Hello World!”
:wq
[root@localhost ~]# bash hello.sh # 运⾏shell
脚本的⽅法1
Hello World!
[root@localhost ~]# sh hello.sh # 运⾏
shell脚本的⽅法2
Hello World!
[root@localhost ~]# chmod +x hello.sh # 运⾏shell脚本
的⽅法3
[root@localhost ~]# ll hello.sh
-rwxr-xr-x. 1 root root 32 6⽉ 14 14:22 hello.sh
[root@localhost ~]# ./hello.sh
Hello World!
[root@localhost ~]# source ./hello.sh # 只在当前环境生效,
其他方法是另外再开一个shell。
Hello World!
[root@localhost ~]# vim hello.sh # 修改hello脚本
#!/bin/bash
echo "Hello World!"
ls -lh /
df -hT
:wq
[root@localhost ~]# sh hello.sh
Hello World!
总⽤量 30K
lrwxrwxrwx. 1 root root 7 10⽉ 11 2021 bin -> usr/bin
dr-xr-xr-x. 5 root root 4.0K 5⽉ 11 20:46 boot
drwxr-xr-x. 19 root root 3.1K 6⽉ 14 22:08 dev
drwxr-xr-x. 144 root root 8.0K 6⽉ 14 22:14 etc
drwxr-xr-x. 3 root root 23 5⽉ 11 20:45 home
lrwxrwxrwx. 1 root root 7 10⽉ 11 2021 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 10⽉ 11 2021 lib64 -> usr/lib64
dr-xr-xr-x. 7 root root 2.0K 11⽉ 11 2022 media
drwxr-xr-x. 3 root root 18 5⽉ 11 20:43 mnt
drwxr-xr-x. 2 root root 6 10⽉ 11 2021 opt
dr-xr-xr-x. 194 root root 0 6⽉ 14 22:08 proc
dr-xr-x---. 15 root root 4.0K 6⽉ 14 22:27 root
drwxr-xr-x. 41 root root 1.2K 6⽉ 14 22:10 run
lrwxrwxrwx. 1 root root 8 10⽉ 11 2021 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 10⽉ 11 2021 srv
dr-xr-xr-x. 13 root root 0 6⽉ 14 22:08 sys
drwxrwxrwt. 5 root root 4.0K 6⽉ 14 22:27 tmp
drwxr-xr-x. 13 root root 158 5⽉ 11 20:43 usr
drwxr-xr-x. 21 root root 4.0K 5⽉ 11 21:13 var
⽂件系统 类型 容量 已⽤ 可⽤ 已⽤% 挂载点
devtmpfs devtmpfs 1.8G 0 1.8G 0% /dev
tmpfs tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs tmpfs 1.9G 9.2M 1.8G 1% /run
tmpfs tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/rl-root xfs 17G 5.8G 12G 34% /
/dev/sr0 iso9660 12G 12G 0 100% /media
/dev/sda1 xfs 1014M 260M 755M 26% /boot
tmpfs tmpfs 371M 0 371M 0% /run/user/0
# 可以看出,shell脚本就是有序的执行其中的命令条件

2、编写 nginx 安装脚本

1. 安装依赖环境
2. 下载 nginx 压缩包
3. 解压
4.make make install 安装
5. 按照顺序执行指令
[root@localhost ~]# vim /root/shell/install_nginx.sh
#!/bin/bash
yum -y install gcc gcc-c++ make pcre-devel openssl-devel
wget
cd /usr/local/src/
wget 'http://nginx.org/download/nginx-1.22.1.tar.gz'
tar xf nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure --prefix=/usr/local/nginx
make -j 4
make install
:wq
# 逻辑顺序:先安装依赖关系,再进入到系统默认的安装包目录src,使用wget
命令从网上下载nginx1.22.1版本的安装包,然后解压,再移动到 nginx 安
装目录,执行编译安装(预配置,编译,编译安装)

四、变量

1、概念

变量用来存放系统或用户需要使用的特定参数或者值,变量的值可以根
据用户设定或者系统环境变化而相应变化,在 Shell 脚本中使用变量,可
使脚本更加灵活,适应性更强。
与变量相对应的是常量,常量例如 “Hello World” ,是不可改变的
变量可以给个变量名,假如为 name ,值是可变的

2、变量注意事项

变量命名规则: 必须由大写字母、小写字母、下划线、数字,并且首字
母不能是数字
在变量命名时:建议也简写出该变量是什么用处
例如:
变量值的类型:值的类型会分为整型、浮点型、字符串型、布尔型等,
而且使用变量需要指定类型 Shell 默认的变量类型都是字符串,无需指
定类型

3、变量的分类

1 )自定义变量
由用户自己定义、使用和修改
[root@localhost ~]# A=1314 # 左边是变量名、右边是值
[root@localhost ~]# echo $A
1314
[root@localhost ~]# unset A # 清除变量
[root@localhost ~]# echo $A
[root@localhost ~]#
变量名 = 值中,等于号 = 之前和之后不能有空格,比如: name = yang
这样是错的, name=yang 才对
变量名 = 值中,值内如果输入数学算式,是没办法算出结果的,只会输
出字符串。
2 )环境变量
由系统维护,用于设置工作环境
 $PWD
 $SHELL
 $USER
$PATH
[root@localhost ~]# env # 查看所有环境变量
...
SSH_CONNECTION=192.168.100.1 56964 192.168.100.100 22
LANG=zh_CN.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=localhost.localdomain
which_declare=declare -f
XDG_SESSION_ID=1
USER=root
SELINUX_ROLE_REQUESTED=
PWD=/root
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/root
SSH_CLIENT=192.168.100.1 56964 22
SELINUX_LEVEL_REQUESTED=
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/va
r/lib/flatpak/ex
ports/share:/usr/local/share:/usr/share
SSH_TTY=/dev/pts/0
MAIL=/var/spool/mail/root
TERM=xterm
SHELL=/bin/bash
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
XDG_RUNTIME_DIR=/run/user/0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/ro
ot/bin
DEBUGINFOD_URLS=https://debuginfod.centos.org/
HISTSIZE=1000
LESSOPEN=||/usr/bin/lesspipe.sh %s
BASH_FUNC_which%%=() { ( alias;
eval ${which_declare} ) | /usr/bin/which --tty-only --
read-alias --read-f
unctions --show-tilde --show-dot $@
}
_=/usr/bin/env
OLDPWD=/root/shell
[root@localhost ~]# echo $PWD
/root
[root@localhost ~]# echo $SHELL
/bin/bash
[root@localhost ~]# echo $USER
root
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bi
n
[root@localhost ~]#
其中 PATH 变量用于设置可执行程序的默认搜索路径,可以修改全局变
量文件 /etc/profile 或修改某用户家目录下的 ~/.bash_profile 文件永久改
变环境变量。
3 )位置变量
通过命令行给脚本程序传递参数 ( 也属于预定义变量 )
为了在使用 Shel 脚本程序时,方便通过命令行为程序提供操作参数,
Bash 引入了位置变量的概念位置变量有 n n 1~9 之间的数字
$0 :第一个字段表示命令名或脚本名称
$1 :脚本要处理的第一个参数
$2 :脚本要处理的第二个参数
....
Shell 脚本最多可以直接处理 9 个参数
[root@localhost shell]# vim ip.sh
#!/bin/bash
ifconfig $1 | grep -w inet | awk '{print $2}' # 设置⼀个参数
:wq
[root@localhost shell]# sh ./ip.sh ens32
192.168.100.100
[root@localhost shell]# vim ip.sh
#!/bin/bash
ifconfig $1$2 | grep -w inet | awk '{print $2}' # 设置两个参
数
:wq
[root@localhost shell]# sh ./ip.sh ens 32
192.168.100.100
[root@localhost shell]#
4 )预定义变量
Bash 中内置的一类变量,不能直接修改
预定义变量是 Bash 程序预先定义好的一类特殊变量,用户只能使用预定
义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。
$* :将所有参数作为整体
$@ :单个参数的组合,每个参数占一行
$0 :保存了脚本名称
$? :保存命令或脚本的执行状态码
$# :保存脚本要处理的参数的个数
[root@localhost shell]# vim hehe.sh
#!/bin/bash
for x in "$*" # 将所有参数整合到一起,总共列为一行
do
echo $x
done
for y in "$@" # 将所有参数单个列出,每个参数单列一行
do
echo $y
done
:wq
[root@localhost shell]# sh ./hehe.sh 1 2 3 4 5 6 #
查看$*和$@的区别
1 2 3 4 5 6 # $*的结果
1
2
3
4
5
6 # $@的结果
[root@localhost shell]# vim hehe.sh
#!/bin/bash
for x in "$*"
do
echo $x
done
for y in "$@"
do
echo $y
done
echo "该脚本是:$0"
echo "此脚本⼀共处理了$#个参数"
:wq
[root@localhost shell]# sh hehe.sh 1 2 3 4 5 6
1 2 3 4 5 6
1
2
3
4
5
6
该脚本是:hehe.sh # $0的结果,也就是该脚本的名称
此脚本⼀共处理了6个参数 # $#的结果,执行脚本时,输入了多少参
数

4、变量的定义与输出

1 )定义一个新的变量
格式:变量名 = 变量值
注意:变量名必须以字母或下划线开头,严格区分大小写
2 )变量符号运用
双引号:允许通过 $ 符号引用其他变量值
单引号:禁止引用其他变量值, $ 视为普通字符
反撇号: 或 $(): 命令替换,提取命令的执行结果
[root@localhost shell]# X=aaa
[root@localhost shell]# echo "$X" # 双引号可以使用变量
aaa
[root@localhost shell]# echo '$X' # 单引号只显示符号内的
字符
$X
[root@localhost shell]# ip1=`ifconfig ens32 | grep -w inet
| awk '{print$2}'` # ``反撇号可以引用命令
[root@localhost shell]# ip2=$(ifconfig ens32 | grep -w
inet | awk '{print$2}') # $()与反撇号作用相同
[root@localhost shell]# echo $ip1
192.168.100.100
[root@localhost shell]# echo $ip2
192.168.100.100
[root@localhost shell]# x=100
[root@localhost shell]# y=50
[root@localhost shell]# z=`expr $x + $y` # 整数运算
[root@localhost shell]# echo $z
150
[root@localhost shell]# x=1.4
[root@localhost shell]# expr $x + 1 # 判断是否为浮点数
expr: ⾮整数参数
[root@localhost shell]# [ $? -ne 0 ] && echo "x为浮点数"
x为浮点数
[root@localhost shell]#
3 )输入和输出
输入格式: read [-p " 显示的提示信息 "] 变量名
输出格式: echo $ 变量名
[root@localhost shell]# read x y # 输⼊,变量输入,在下
一行输入
1 3
[root@localhost shell]# echo $x $y # 输出,直接输出变量
1 3
[root@localhost shell]# read -p "请输⼊你要赋值的变量值" x y
请输⼊你要赋值的变量值1 5
[root@localhost shell]# echo $x $y
1 5
[root@localhost shell]# vim ip.sh # 编写一个查看IP的脚
本,内容如下
#!/bin/bash
read -p "请输⼊接⼝名称:" x # 输入x变量等于什么,脚本内不
用写,命令行输入该变量x等于什么即可,该变量x可在脚本内引用
ifconfig $x | grep -w inet | awk '{print $2}'
:wq
[root@localhost shell]# sh ip.sh
请输⼊接⼝名称:ens32
192.168.100.100
[root@localhost shell]# sh ip.sh
请输⼊接⼝名称:lo
127.0.0.1
[root@localhost shell]# vim read.sh # 编写输入账号密码的脚
本,内容如下
#!/bin/bash
read -p "请输⼊您的姓名:" name # 该变量name是在命令行输入
的,相当于变量=值
read -p "请输⼊您的密码:" passwd # 该变量passwd是在命令行输入
的,相当于变量=值
if [ $passwd = "123456" ]; then # if判断语句,如果(if)某某
等于某某,那么(then)执行什么命令,否则(else)执行什么命令,结尾fi
echo "你好,$name !"
else
echo "抱歉,您输⼊的密码不正确!"
fi
:wq
[root@localhost shell]# sh read.sh
请输⼊您的姓名:admin
请输⼊您的密码:112233
抱歉,您输⼊的密码不正确!
[root@localhost shell]# sh read.sh
请输⼊您的姓名:admin
请输⼊您的密码:123456
你好,admin !
[root@localhost shell]#

5、变量的作用范围

默认情况下,新定义的变量只在当前 Shell 环境中有效,因此称为局部变
量。当进入子程序或新的子 shell 时,局部变量将无法再使用。
为了使用户定义的变量在所有子 Shell 环境中能够继续使用,减少重复设
置工作,可以通过内部命令 export 将指定的变量导出为 全局变量
格式 1 export 变量名
格式 2 export 变量名 =
[root@localhost shell]# x=aaa
[root@localhost shell]# export y=bbb # 使y=bbb导出为
全局变量,即使下次更新环境变量,y也会生效,相当于在/etc/profile内永
久赋值
[root@localhost shell]# hostname shell
[root@localhost shell]# bash
[root@shell shell]# echo $x
[root@shell shell]# echo $y
bbb
[root@shell shell]#
6 、变量的数学运算
1 )整数运算
格式: expr 变量 1 运算符 变量 2 运算符 变量 3....
运算符: + - * / + - × ÷
[root@shell shell]# x=123
[root@shell shell]# y=111
[root@shell shell]# expr $x + $y # 加
234
[root@shell shell]# expr $x - $y # 减
12
[root@shell shell]# expr $x \* $y # 乘
13653
[root@shell shell]# expr $x / $y # 除
1
[root@shell shell]# expr $x % $y # 余数计算
12
[root@shell shell]#
2 )精度计算
[root@shell shell]# yum -y install bc # 精度计算前,先
安装bc这个软件才可进行,否则只能进行整数运算
上次元数据过期检查:2:45:58 前,执⾏于 2023年06⽉14⽇ 星期三 22时
21分58秒。
软件包 bc-1.07.1-5.el8.x86_64 已安装。
依赖关系解决。
⽆需任何处理。
完毕!
[root@shell shell]# x=123
[root@shell shell]# y=111
[root@shell shell]# echo "scale=5; $x / $y" | bc
1.10810
[root@shell shell]#

五.判断语法

1、条件判断

Shell 的返回值:运行一条命令,都会有一个返回值。 0 代表执行正常,非 0 代表命令执行异常。
[root@localhost test]# ls /
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
[root@localhost test]# echo $? # $?保存了上条命令的返回值,0表示执行成功,非0表示执
行失败
0
[root@localhost test]# ls /haha
ls: ⽆法访问'/haha': 没有那个⽂件或⽬录
[root@localhost test]# echo $?
2
[root@localhost test]#

2、if 条件判断语句

1 if 单分支语句
if 条件判断 ; then
条件成 的命令 ( 可以有多个命令,命令执行方式为逐行执行要么全执行,要么全不执行 )
fi
2 if 多分支语句
if 条件判断 ; then
条件成 的命令 ( 可以有多个命令 )
else
条件不成 的命令 ( 可以有多个命令 )
fi
条件判断:可以有数字判断、字符串判断、⽂件判断等

3、数字判断

1 、格式
-eq equal ,等于,一般用于 [ $? -eq 0 ] ,也就是判断上条命令返回值等于 0 ,直接数字 -eq
字也可以 equals
-ne not equal ,不等于,一般用于 [ $? -ne 0 ] ,判断上条命令返回值不等于 0
-gt greater than ,大于
-ge greater or equal ,大于或等于
-lt less than ,小于
-le less or equal ,小于或等于
2 、应用示例
[root@localhost test]# test 2 -eq 2 # test:shell环境中,测试条件表达式的命令工具
[root@localhost test]# echo $?
0
[root@localhost test]# test 3 -eq 2 # 测试3等于2
[root@localhost test]# echo $?
1 # 返回值为1,说明测试的3等于2这条命令不成立
[root@localhost test]# [ 2 -eq 2 ] # 编程中习惯使⽤[ ]中括号
[root@localhost test]# echo $?
0
[root@localhost test]# [ 3 -eq 2 ]
[root@localhost test]# echo $?
1
[root@localhost test]#
3 、创建简单的数字判断脚本
[root@localhost test]# vim if.sh
#!/bin/bash
num1=3 # 给定变量num1
num2=3 # 给定变量num2
if [ $num1 -eq $num2 ];then # 判断num1变量是否等于num2
echo "$num1 equal $num2" # 如果等于,那么执行命令,echo输出
echo "in if"
fi
:wq
[root@localhost test]# sh ./if.sh
3 equal 3
in if
[root@localhost test]#
4 、创建检测网络是否畅通的脚本
[root@localhost test]# vim ping.sh
#!/bin/bash
read -p "请输⼊要测试的⽹址:" web # read:命令行内输入web的变量值
ping -c 3 $web &> /dev/null # ping -c 3,连接某个网站三次
if [ $? -eq 0 ];then # 如果ping命令执行成功,那么
echo "此时⽹络畅通!" # 输出“此时网络畅通”
else # 否则
echo "⽆法访问,请检查⽹址是否输⼊正确或检查相关的⽹络配置!" # 输出“无法访
问...”
fi # if语句的结尾
:wq
[root@localhost test]# sh ./ping.sh
请输⼊要测试的⽹址:www.baidu.com
此时⽹络畅通!
[root@localhost test]#

4、字符串判断

1 、格式
[ 字符串 1 == 字符串 2 ] 字符串内容相同
[ 字符串 1 != 字符串 2 ] 字符串内容不同
[ -z 字符串 ]
字符串内容为空
[ -n 字符串 ]
字符串内容不为空
[root@localhost test]# [ aaa == aaa ] # aaa字符串等于aaa
[root@localhost test]# echo $?
0 # 命令返回值为0,说明aaa==aaa
[root@localhost test]# [ aaa == bbb ] # aaa字符串等于bbb
[root@localhost test]# echo $?
1 # 命令返回值为非0,说明aaa不等于bbb
[root@localhost test]# [ -z aaa ] # aaa字符串为空字符串
[root@localhost test]# echo $?
1 # 命令返回值为非0,说明aaa字符串不为空
[root@localhost test]# [ -z ] # 直接引用空字符串
[root@localhost test]# echo $?
0 # 命令返回值为0,说明上条判断命令为空字符串
[root@localhost test]# [ -n aaa ] # aaa为非空字符串
[root@localhost test]# echo $?
0 # 命令返回值为0,说明aaa为非空字符串
[root@localhost test]#
3 、案例
1 )创建简单的字符串判断脚本
[root@localhost test]# vim zifu.sh
#!/bin/bash
read -p "请输⼊账号:" name
if [ "$name" == "admin" ];then # 字符串判断需要加双引号
echo "欢迎您,$name!"
else
echo "系统未查询到此账号,请您重新输⼊!"
fi
:wq
[root@localhost test]# sh ./zifu.sh
请输⼊账号:admin
欢迎您,admin!
[root@localhost test]# sh ./zifu.sh
请输⼊账号:ads
系统未查询到此账号,请您重新输⼊!
[root@localhost test]#
2 )创建 rpm 查询软件是否安装的脚本
[root@localhost test]# vim rpm.sh
#!/bin/bash
read -p "请输⼊你要检测的rpm包:" rpmname # 命令行输入rpmname变量值
result=`rpm -qa $rpmname` # 设置result变量为`rpm -qa $rpmname`命令
if [ -z "$result" ];then # 判断result变量内的命令执行后的值是否为空
echo "${rpmname} is not find!" # 如果为空则输出这条
else
echo "${rpmname} is find!" # 否则输出这条
fi
:wq
[root@localhost test]# sh ./rpm.sh
请输⼊你要检测的rpm包:nginx
nginx is not find!
[root@localhost test]# sh ./rpm.sh
请输⼊你要检测的rpm包:lrzsz
lrzsz is find!
[root@localhost test]#

5、文件、目录、权限的判断

1 、格式
[ 操作符 文件或目录 ]
常用的测试操作符 :
2 、示例
[root@localhost test]# [ -e "/etc/passwd" ] # 判断/etc/passwd文件是否存在
[root@localhost test]# echo $?
0
[root@localhost test]# [ -e "/etc/haha" ] # 判断/etc/haha文件是否存在
[root@localhost test]# echo $?
1
[root@localhost test]# [ -f "/etc" ] # 判断/etc是否为普通文件
[root@localhost test]# echo $?
1
[root@localhost test]# [ -x "/bin/bash" ] # 判断/bin/bash是否可执行
[root@localhost test]# echo $?
0
[root@localhost test]
3 、案例
nginx 安装脚本优化,判断是否已安装 nginx
[root@localhost test]# vim install_nginx.sh
#!/bin/bash
if [ -e "/usr/local/nginx" ];then # -e:判断nginx软件目录是否存在
echo "nginx is install!" # 存在则输出一条nginx已安装的提示信息
exit 1 # 输出完已安装信息则退出脚本
else # 若nginx软件目录不存在,则执行如下命令
yum -y install gcc gcc-c++ make pcre-devel openssl-devel wget
cd /usr/local/src/
wget 'http://nginx.org/download/nginx-1.22.1.tar.gz'
tar xf nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure --prefix=/usr/local/nginx
make -j 4&&make install
ln -s /usr/local/nginx/sbin/nginx /usr/bin/
/usr/local/nginx/sbin/nginx
fi
:wq
[root@localhost test]# sh ./install_nginx.sh

6、与或判断

判断多个条件
多个条件其中一个成立,或
多个条件都要成立,与
或运算判断: ||
或,两个条件满足其一即可,还有 -o
与运算判断: && 与,两个条件都得满足才行,还有 -a
1 、或运算判断
[root@localhost test]# vim huo.sh
#!/bin/bash
read -p "请输⼊字符串:" name
if [ "$name" == "haha" ]||[ "$name" == "hehe" ];then # 这两个条件需满足其
一,也可使⽤[ "$name" =="haha" -o "$name" == "hehe" ]
echo "$name is my want"
else
echo "in else"
fi
:wq
[root@localhost test]# sh ./huo.sh
请输⼊字符串:haha
haha is my want
[root@localhost test]# sh ./huo.sh
请输⼊字符串:hehe
hehe is my want
[root@localhost test]# sh ./huo.sh
请输⼊字符串:lala
in else
[root@localhost test]#
2 、与运算判断
[root@localhost test]# vim yu.sh
#!/bin/bash
read -p "请输⼊⼀个数值:" age
if [ $age -gt 30 ]&&[ $age -lt 80 ];then # 这两个条件都得满足,大于30且小于
80,可使用[ $age -gt 30 -a $age -lt 80 ]
echo "age>30 and age<80"
echo "working"
else
echo "in else"
fi
:wq
[root@localhost test]# sh ./yu.sh
请输⼊⼀个数值:60
age>30 and age<80
working
[root@localhost test]# sh ./yu.sh
请输⼊⼀个数值:90
in else
[root@localhost test]#
3 、混合判断
[root@localhost test]# vim hun.sh
#!/bin/bash
read -p "请输⼊⼀个数值:" age
if [ $age -gt 2 ]&&[ $age -lt 10 ]||[ $age -eq 100 ];then # 先做||前面的与判
断,再进行或判断,可使⽤[ $age -gt 2 -a $age -lt 10 -o $age -eq 100 ]
echo "age is>2 and age is <10 or age ==100 "
else
echo "in else"
fi
:wq
[root@localhost test]# sh ./hun.sh
请输⼊⼀个数值:7
age is>2 and age is <10 or age ==100
[root@localhost test]# sh ./hun.sh
请输⼊⼀个数值:100
age is>2 and age is <10 or age ==100
[root@localhost test]# sh ./hun.sh
请输⼊⼀个数值:30
in else
[root@localhost test]#

7、多重判断语法 elif

1 if 多分支语句结构
if 条件1; then
#命令,条件1成⽴执⾏
elif 条件2;then
#命令,条件1不成⽴,条件2成⽴执⾏
elif 条件3;then
#命令,条件1不成⽴,条件2不成⽴,条件3成⽴执⾏
else
#命令 ,以上条件都不成⽴执⾏
fi
2 、案例
[root@localhost test]# vim fs.sh
#!/bin/bash
#分数等级评定
read -p "请输⼊您的分数(0-100):" fs
if [ $fs -ge 0 -a $fs -lt 60 ];then
echo "$fs分,不及格!"
elif [ $fs -ge 60 -a $fs -lt 70 ];then
echo "$fs分,及格!"
elif [ $fs -ge 70 -a $fs -lt 85 ];then
echo "$fs分,良好!"
elif [ $fs -ge 85 -a $fs -le 100 ];then
echo "$fs分,优秀!"
else
echo "您输⼊的分数有误!"
fi
:wq
[root@localhost test]# sh ./fs.sh
请输⼊您的分数(0-100):20
20分,不及格!
[root@localhost test]# sh ./fs.sh
请输⼊您的分数(0-100):85
85分,优秀!
[root@localhost test]# sh ./fs.sh
请输⼊您的分数(0-100):70
70分,良好!
[root@localhost test]# sh ./fs.sh
请输⼊您的分数(0-100):123
您输⼊的分数有误!
[root@localhost test]#

8、多重判断的 case 语句

1 case 语句概述
case 语句是多分支选择语句
使用 case 语句改写 if 多分支可以使脚本结构更加清晰、层次分明。针对变量的不同取值,执行不同
的命令序列, case 还支持正则。
2 case 语句的结构
case $ 量名称 in
模式 1)
命令序列 1
;;
模式 2)
命令序列 2
;;
*)
默认命令序列
esac
3 、示例
提示用户输入一个字符,判断该字符是字母、数字或者其他字符的脚本
[root@localhost test]# vim hitkey.sh
#!/bin/bash
#击键类型识别
read -p "请输⼊⼀个字符,并按Enter键确认:" key
case $key in
[a-z]|[A-Z]) # a到z或A到Z,当变量输入为字母则执行下面的echo命令
echo "您输⼊的是⼀个 字⺟"
;;
[0-9]) # 0到9,当变量输入为数字则执行下面的echo的命令
echo "您输⼊的是⼀个 数字"
;;
*) # 若变量输入为空格等其他符号字符,则执行下
面的echo命令
echo "您输⼊的是 空格、功能键或其他控制字符"
;;
esac
:wq
[root@localhost test]# sh ./hitkey.sh
请输⼊⼀个字符,并按Enter键确认:5
您输⼊的是⼀个 数字
[root@localhost test]# sh ./hitkey.sh
请输⼊⼀个字符,并按Enter键确认:b
您输⼊的是⼀个 字⺟
[root@localhost test]# sh ./hitkey.sh
请输⼊⼀个字符,并按Enter键确认:P
您输⼊的是⼀个 字⺟
[root@localhost test]# sh ./hitkey.sh
请输⼊⼀个字符,并按Enter键确认:!
您输⼊的是 空格、功能键或其他控制字符
[root@localhost test]#
4 、案例
输入分数变量,然后判定等级
[root@localhost test]# vim fscase.sh
#!/bin/bash
#使⽤case语句编写分数等级评定脚本
read -p "请输⼊您的分数(0-100):" fs
case $fs in
[0-9]|[0-5][0-9]) # 0到9或59以内的两位数
echo "$fs分,不及格!"
;;
6[0-9]) # 6开头的两位数,若$fs输入为0,则判定为60,即执行下面的echo命令
echo "$fs分,及格!"
;;
7[0-9]|8[0-5]) # 以7开头的两位数或以8开头的两位数
echo "$fs分,良好!"
;;
8[6-9]|9[0-9]|100) # 以8开头的两位数,第二位最少为6,也就是最小是86 | 以9
开头的两位数 | 100
echo "$fs分,优秀!"
;;
*) # 输入不在上述规则内的其他字符,则echo如下命令
echo "您输⼊的分数有误!"
esac
:wq
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):5
5分,不及格!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):58
58分,不及格!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):69
69分,及格!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):70
70分,良好!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):89
89分,优秀!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):100
100分,优秀!
[root@localhost test]# sh ./fscase.sh
请输⼊您的分数(0-100):110
您输⼊的分数有误!
[root@localhost test]#

六.循环语法

1、for 循环

1 、作用
读取不同的变量值,以逐个执行同一组命令
2 、结构
for 变量名 in 取值列表 ( 范围 )
do
命令序列
done
取值列表:数字范围、字符串、多个字符串、提前设定好的变量等
for 默认以所有的空白字符进行分隔 : tab 、空格、回车,去循环处理
分隔成几段就循环几次
3 、示例
1 )分隔值循环
[root@localhost test]# vim quzhi.sh
#!/bin/bash
for home in 北京 上海 ⼴州 深圳 # home变量在北京、上海、广州、深圳这四个地名中间循环一
次
do
echo "$home 是个好地⽅!"
done
:wq
[root@localhost test]# bash quzhi.sh
北京 是个好地⽅!
上海 是个好地⽅!
⼴州 是个好地⽅!
深圳 是个好地⽅!
[root@localhost test]#
2 )在命令结果中循环
[root@localhost test]# vim 1.sh
#!/bin/bash
x=1
for user in $(awk -F':' '{print $1}' /etc/passwd) # 在/etc/passwd文件中以用
户名作为循环
do
echo "第 $x ⽤户名称为: $user"
let x=x+1
done
echo "该系统有 $(($x-1)) 个⽤户"
:wq
[root@localhost test]# bash 1.sh
第 1 ⽤户名称为: root
...省略部分内容
第 45 ⽤户名称为: yunjisuan
第 46 ⽤户名称为: apache
第 47 ⽤户名称为: nginx
该系统有 47 个⽤户
[root@localhost test]#
3 )检测某个网段的存活主机
[root@localhost test]# vim ping.sh
#!/bin/bash
for IP in $(echo 192.168.33.{100..120}) # 192.168.33网段的100到120的主机,在此
循环
do
ping -c 2 -i 0.1 $IP &> /dev/null
if [ $? -eq 0 ];then
echo "Host $IP is up."
fi
done
:wq
[root@localhost test]# bash ping.sh
Host 192.168.100.100 is up.
Host 192.168.100.101 is up.
[root@localhost test]#
4 )判断包是否已安装
[root@localhost test]# vim 2.sh
#!/bin/bash
for softpack in wget gcc pcre pcre-devel zlib zlib-devel;do
soft_result=$(rpm -qa $softpack)
if [ -z "$soft_result" ];then
yum install -y $softpack
else
echo "$softpack is installed"
fi
done
[root@localhost test]# bash 2.sh
wget is installed
gcc is installed
pcre is installed
pcre-devel is installed
zlib is installed
zlib-devel is installed
[root@localhost test]#

2、while 循环

1 、作用
重复测试某个条件,只要条件成立则反复执行
2 、结构
while 条件测试操作
do
命令序列
done
3 while for 区别
while 循环也有条件判断,当条件成立的时候,会循环执行。当条件不成立退出
if 判断当条件成立时,会执行一次,然后退出。当条件不成立时直接退出
4 、示例
1 )批量添加用户
创建时交互输入用户前缀、创建用户个数、初始密码、过期时间 ( 可选设置 ) ,用户首次登陆强制要
求修改密码
[root@localhost test]# vim useradd.sh # 批量创建⽤户脚本
#!/bin/bash
read -p "请输⼊创建⽤户的名称前缀:" QZ
read -p "请输⼊创建⽤户的个数:" NUM
read -p "请输⼊⽤户的初始密码:" PS
i=1
while [ $i -le $NUM ]
do
useradd $QZ$i
echo "$PS" |passwd --stdin $QZ$i &> /dev/null
chage -d 0 $QZ$i
let i++
done
:wq
[root@localhost test]# bash useradd.sh
请输⼊创建⽤户的名称前缀:admin
请输⼊创建⽤户的个数:5
请输⼊⽤户的初始密码:123456
[root@localhost test]# tail /etc/passwd
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
yunjisuan:x:1000:1000:yunjisuan:/home/yunjisuan:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
nginx:x:975:974:Nginx web server:/var/lib/nginx:/sbin/nologin
admin1:x:1001:1001::/home/admin1:/bin/bash
admin2:x:1002:1002::/home/admin2:/bin/bash
admin3:x:1003:1003::/home/admin3:/bin/bash
admin4:x:1004:1004::/home/admin4:/bin/bash
admin5:x:1005:1005::/home/admin5:/bin/bash
[root@localhost test]# vim userdel.sh # 批量删除⽤户脚本
#!/bin/bash
read -p "请输⼊要删除⽤户的前缀:" QZ
read -p "请输⼊要删除⽤户的个数:" NUM
i=1
while [ $i -le $NUM ]
do
userdel -r $QZ$i
let i++
done
:wq
[root@localhost test]# bash userdel.sh
请输⼊要删除⽤户的前缀:admin
请输⼊要删除⽤户的个数:5
[root@localhost test]#

3、循环的 break continue

break 直接结束循环,循环立即退出
continue 可以用来跳过一次循环,跳过后循环继续,直到循环停止
1 、示例
[root@localhost test]# vim test.sh
#!/bin/bash
for line in 北京 上海 ⼴州 深圳
do
echo $line
if [ "$line" == "上海" ];then $ 循环到上海⽴即退出
break
fi
done
:wq
[root@localhost test]# bash test.sh
北京
上海
[root@localhost test]# vim test.sh
#!/bin/bash
for line in 北京 上海 ⼴州 深圳
do
if [ "$line" == "上海" ];then
continue
fi
echo $line
done
:wq
[root@localhost test]# bash test.sh
北京
⼴州
深圳
[root@localhost test]#
2、九九乘法表
[root@localhost test]# vim 99.sh
#!/bin/bash
#九九乘法表
for i in {1..9};do
for j in {1..9};do
echo -n "$j*$i=$(($i*$j)) "
if [ $j == $i ];then
echo -e '\n'
break
fi
done
done
:wq
[root@localhost test]# bash 99.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
[root@localhost test]#
[root@localhost test]# vim 99-2.sh
#!/bin/bash
#九九乘法表
i=1
while [ $i -le 9 ];do
j=1
while [ $j -le 9 ];do
echo -n "$j*$i=$(($i*$j)) "
if [ $j -eq $i ];then
echo -e '\n'
break
fi
let j++
done
let i++
done
:wq
[root@localhost test]# bash 99-2.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
[root@localhost test]#

七.sed流式编译器

1、概述

sed 是文本处理工具,读取文本内容,根据指定条件进行处理,可实现
增删改查的功能。 sed 依赖于正则表达式。
1 、格式
sed ' 过滤 + 动作 ' 文件路径
2 、选项

2、编辑命令格式

'/ 地址 1 ,地址 2/ 操作 ( 参数 )'
1 、地址
可为行数、正则表达式、 $ ,没有地址代表全文
2 、操作

3、示例

1 )准备文件
[root@localhost test]# vim test.txt
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
:wq
[root@localhost test]#
2 p 打印
[root@localhost test]# sed -n '12p' test.txt #
输出第12⾏内容
HELLO
[root@localhost test]# sed -n '3,5p' test.txt # 输出
3~5⾏内容
good
goood
gooood
[root@localhost test]# sed -n 'p;n' test.txt #
输出奇数⾏
gd
good
gooood
glad
abcdEfg
60115127Z
010-66668888
IP 192.168.1.108
pay $180
[root@localhost test]# sed -n 'n;p' test.txt #
输出偶数⾏
god
goood
gold
gaad
food
HELLO
0666-5666888
IP 173.16.16.1
[root@localhost test]# sed -n '1,6{p;n}' test.txt # 输出1~6
⾏之间的奇数⾏(第1,3,5⾏)
gd
good
gooood
[root@localhost test]# sed -n '/H/p' test.txt # 输出
包含字⺟H的⾏
HELLO
[root@localhost test]# sed -n '/[A-Z]/p' test.txt # 输出所有
包含⼤写字⺟的⾏
abcdEfg
60115127Z
HELLO
IP 192.168.1.108
IP 173.16.16.1
[root@localhost test]# sed -n '$p' test.txt #
输出最后⼀⾏
pay $180
[root@localhost test]#
3 d 删除
[root@localhost test]# sed '16d' test.txt # 删除第十六
行
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
pay $180
[root@localhost test]# cat -n test.txt
1 gd
2 god
3 good
4 goood
5 gooood
6
7 gold
8 glad
9
10 gaad
11 abcdEfg
12 food
13
14 60115127Z
15 HELLO
16 010-66668888
17 0666-5666888
18 IP 192.168.1.108
19 IP 173.16.16.1
20 pay $180
[root@localhost test]# sed -i '/^$/d' test.txt # 删除
空行,^$:表示空行
[root@localhost test]# cat -n test.txt
1 gd
2 god
3 good
4 goood
5 gooood
6 gold
7 glad
8 gaad
9 abcdEfg
10 food
11 60115127Z
12 HELLO
13 010-66668888
14 0666-5666888
15 IP 192.168.1.108
16 IP 173.16.16.1
17 pay $180
[root@localhost test]# sed -e '1d' -e '3d' test.txt #
删除第1⾏和第3⾏
god
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]# sed -e '1d;3d' test.txt
# 同样,删除第1⾏和第3⾏
god
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]#
4 s 替换字符串
[root@localhost test]# sed 's/o/O/g' test.txt # 将所
有⼩写o替换为⼤写O(g表示若同⼀⾏有多个⼩写o,全部替换,若不加g,则只
替换每⾏的第⼀个⼩写o)
gd
gOd
gOOd
gOOOd
gOOOOd
gOld
glad
gaad
abcdEfg
fOOd
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]# sed '/^IP/ s/^/#/' test.txt #
以IP开头的⾏,⾏⾸加上
#
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
#IP 192.168.1.108
#IP 173.16.16.1
pay $180
[root@localhost test]# sed 's/$/EOF/' test.txt # 在每
⾏⾏尾插⼊字符串EOF
gdEOF
godEOF
goodEOF
gooodEOF
goooodEOF
goldEOF
gladEOF
gaadEOF
abcdEfgEOF
foodEOF
60115127ZEOF
HELLOEOF
010-66668888EOF
0666-5666888EOF
IP 192.168.1.108EOF
IP 173.16.16.1EOF
pay $180EOF
[root@localhost test]# sed '20,25
s@/sbin/nologin@/bin/bash@' /etc/passwd
# 将/etc/passwd⽂件20~25⾏的/sbin/nologin替换为/bin/bash。如
果⽤s///的形式,将会多次使⽤转义符\,我们可以使⽤其他符号,如@进⾏分隔
5 c 替换整行
[root@localhost test]# sed '2cAAAAAAA' test.txt #
将第2⾏替换为AAAAA
gd
AAAAAAA
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]# sed '5,$ cAAAAA\nBBBBB' test.txt
# 把第5⾏⾄最后⼀⾏的内容替换为两⾏,AAAAA和BBBBB(\n为换⾏)
gd
god
good
goood
AAAAA
BBBBB
[root@localhost test]#
6 r 追加指定文件到行后
[root@localhost test]# sed '5r /etc/hostname' test.txt # 读
取/etc/hostname⽂件内容在第5⾏后
gd
god
good
goood
gooood
localhost.localdomain
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]#
7 a 追加指定内容到行后
[root@localhost test]# sed '2aCCCCCCCCC' test.txt #
在第二行后追加9个C
gd
god
CCCCCCCCC
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]# sed '/[0-9]/a=====' test.txt #
在所有带数字的⾏下追
加====
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
=====
HELLO
010-66668888
=====
0666-5666888
=====
IP 192.168.1.108
=====
IP 173.16.16.1
=====
pay $180
=====
[root@localhost test]#
8 i 追加指定内容到行前
[root@localhost test]# sed '2iCCCCC' test.txt # 在第
二行之前追加5个C
gd
CCCCC
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]#
9 w 另存为
[root@localhost test]# sed '15,16w 123.txt' test.txt
# 将15~16⾏内容另存到123.txt⽂件中
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
IP 173.16.16.1
pay $180
[root@localhost test]# cat 123.txt
IP 192.168.1.108
IP 173.16.16.1
[root@localhost test]#
10 H G 复制剪切粘贴
H :复制到剪贴板
G :将剪贴板中的内容追加到指定行后
[root@localhost test]# sed '/IP/ {H;d};$G' test.txt
# 将包含字⺟IP的⾏剪切到最后⼀⾏下
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
pay $180
IP 192.168.1.108
IP 173.16.16.1
[root@localhost test]# sed '1,5H;15,16G' test.txt #
将1~5⾏内容复制到15⾏、16⾏下
gd
god
good
goood
gooood
gold
glad
gaad
abcdEfg
food
60115127Z
HELLO
010-66668888
0666-5666888
IP 192.168.1.108
gd
god
good
goood
gooood
IP 173.16.16.1
gd
god
good
goood
gooood
pay $180
[root@localhost test]#

4、sed 命令引用变量

1. sed 命令使用单引号的情况下,可以使用 '"$var"' 引用(单引号,然后
双引号,变量):
sed -i '2s/node_base/'"$i"'/' /etc/libvirt/qemu/$i.xml
1. sed 命令中使用双引号的情况下,直接 shell command 或者 $(shell
command) 引用命令执行。
sed -i "2s/node_base/$i/" /etc/libvirt/qemu/$i.xml
  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值