shell 脚本基础笔记(全)

bash

脚本的介绍及编写脚本的语法

a脚本调试:
检测脚本中的语法错误:bash -n 文件名
注: 只能检测 语法错误 并不能检测命令语法不存在;
在这里插入图片描述
调试执行:bash –x 脚本名 / sh -x 脚本名 ,该方法是通过一行一行执行,有报错的后会提示出来。
在这里插入图片描述

解释器是一种命令解释器,主要作用是对命令进行运行和解释,将需要执行的操作传递给操作系统内核并执行,shell 常见的解释器有:

 	#!/bin/bash (默认)
 	#!/bin/ksh
 	#!/bin/bsh
 	#!/bin/sh

shelll脚本编程:
变成语言的分类:根据运行方式
编译运行:源代码–>编译器(编译)–>程序文件
解释运行:源代码–>运行时启动解释器,由解释器边解释边运行;
编辑模型:过程式编程语言,面向对象的变成语言
程序=指令+数据
过程式:以指令为中心来组织代码,数据是服务于代码
顺序执行
选择执行
循环执行
对象式:以数据为中心来组织代码,围绕数据来组织命令;
类(class):实例化对象,
shell脚本命令的工作方式有两种:交互式和批处理
交互式:用户每输入一条命令就立即执行
批处理:由用户事先编辑好的一个完整的shell脚本,shell会一次性执行脚本中的诸多命令。

查看默认命令行终端解释器:echo $SHELL

配置提示符:username@hostname$root@hostname # 或简单的显示为$/#
$表示普通用户,#表示管理员用户root。
在这里插入图片描述
如何写shell脚本:
脚本文件的第一行:给出shebang,解释器路径,用于指明解释器程当前脚本的解释器文件
shell脚本通常以shebang起始:#!/bin/bash(不加也不会报错)
shebang是一个文本行,其实#!位于解释器路径之前,/bin/bashbash的解释器命令路径。将以#

编写一个简单的shell脚本:
vim ls.sh

#!/bin/bash
#后面跟注释内容,方便以后打开能知道这脚本是干啥的
pwd 
ls -al

运行脚本:sh ls.sh
另外一种运行方式./ls.sh但这种需要执行权限 :chomd +x ls.sh 即可
直接写进脚本里的方式(一般没人用这方法,了解就行):
1) 赋予执行权限,并直接运行次程序文件:

1.	chmod +x /PATH/TO/SCRIPT_FILE
1.	/PATH/TO/SCRIPT_FILE
  1. 直接运行解释器,将脚本以命令行参数 传递给解释器程序
    bash /PATH/TO/SCRIPT_FILE

写一个简单但能接收用户输入参数的shell脚本:
vim ex.sh

#!/bin/bash
echo "当前脚本名称为$0"
echo "总共有$#个参数,分别是$*。"
echo "第一个参数为$1,第五个参数为$5。"

运行脚本:sh ex.sh one two three four five six serven
运行结果:

当前脚本名称为ex.sh
总共有7个参数,分别是one tow three four five six serven
第一个参数为one,第五个参数为five

在这里插入图片描述

bash的配置文件介绍

两类:
	`profile`类:为交互式登陆的shell进程提供配置
	`bashrc`类:为非交互式登陆的shell进程提供配置
登陆类型:
	交互式登陆shell进程:
		直接通过某终端输入账号和密码后打开的shell进程;
		使用su命令:`su - USERNAME`,或者使用`su -| USERNAME`执行的登陆切换
	非交互式登陆shell进程:
		`su - USERNAME`执行的登陆切换
		图形界面下打开的终端
		运行脚本
profile类:
	全局:对所有用户都生效
	`	/etc/profile`
		`/etc/profile.d/*.sh`
	用户个人:仅对当前用户有效:
		`~/.bash_profile`
	功能:
		1:用于定义环境变量
		2:用于命令或脚本
`bashrc`类:
	全局:
	`	/etc/bashrc`
	用户个人:
		`~/.bashrc`
	功能:
		1:定义本地变量
		2:定义命令别名
	注意:仅管理员可修改全局配置文件

交互式登陆shell进程;
`	/etc/profile --> /etc/porfile.d/* .sh--> ~/.bashrc --> /etc/bashrc`
非交互式登陆shell进程:
	`~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh`

命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
配置文件定义的特性,只对随后新启动的shell进程有效。
如:添加一个仅对当前用户有效的bash命令:
vim .bashrc
alias cls='clear'
不会立即生效 需要 . .bashrc后才会生效
在这里插入图片描述
当前用户 执行cls命令 即clear命令
如:让所有用户登陆的时候会收到一个自定义提示和当前时间:

  	vim /etc/profile.d/tishi.sh
  		echo "hello  times: `date` "

在这里插入图片描述

定义环境变量介绍

如:定义一个java变量:
vim /etc/profile.d/java.sh

export JAVA_HOME=/user  
#注:export是定义变量的命令

重读一下 . /etc/profile.d/java.sh生效
export 查看
在这里插入图片描述

让通过配置文件定义的特性立即生效

1) 通过命令行重复定义一次;
2) 让shell进程重读配置文件;
source /PATH/FROM/CONF_FILE
./PATH/FROM/CONF_FILE
在这里插入图片描述

提取ip:

ifconfig | egrp -o "'\<(([0-9] | [1-9] [0-9] | 1[0-9] [0-9] | 2[0-4] [0-9] | 25[0-5])\.) {3} ([0-9] | [1-9] [0-9] | 1[0-9] [0-9] | 2[0-4] [0-9] | 25[0-5])\>"

查看 脚本运行路径: hash
删除其中一个路径: hash -d 名称
删除全部路径: hash -r
在这里插入图片描述

'$'符号后面的参数说明

$0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1…9
$* 这个程式的所有参数,此选项参数可超过9个。
$#这个程式的参数个数
$$ 这个程式的PID(脚本运行的当前进程ID号)
$! 执行上一个背景指令的PID(后台运行的最后一个进程的进程ID号)
$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$- 显示shell使用的当前选项,与set命令功能相同
$@ 跟$*类似,但是可以当作数组用

三种引号的使用

单引号

'':单引号将其中的内容都作为了字符串来,忽略所有的命令和特殊字符,类似于一个字符串的用法

在这里插入图片描述

双引号

"":双引号与单引号的区别在于其可以包含特殊字符(单引号直接输出内部字符串,不解析特殊字符;双引号内则会解析特殊字符),包括’, ", $, ,如果要忽略特殊字符,就可以利用\来转义,忽略特殊字符,作为普通字符输出:
在这里插入图片描述

反引号

`` :反引号用来包含一个命令字符串的,其中的命令会先执行,得到的结果会返回到层命令再执行:
在这里插入图片描述

返回值介绍

正确的话,返回值是0
不正确的话返回值有很多类型 但为非0 即为不正确
返回值纪录在$? 里(使用方法,先执行一个命令,然后执行echo $?返回值是0则正确0则不正确)
在这里插入图片描述
返回值$?仅纪录上一条执行是否成功,不仅输入错误会返回非0值,逻辑错误也会返回非0值,逻辑错误有很多,未查询到结果,ping一个ip不同也属于逻辑错误。。。
在这里插入图片描述
在编写shell脚本的时候我们要querString上一条命令有没有执行成功,可以通过$?返回值判断。
再比如:现在查看grup密码是否设置了,可以通过$?来判断,如下

#! /bin/bash
grup_pwd=`cat /etc/grub.conf | grep -v ^# | grep password 2> /dev/null`

if [ $? -eq 0 ];then  #返回值是否等于0
   echo "  [ √ ] 已设置grub密码,符合要求"  #等于0
else
   echo "  [ X ] 没有设置grub密码,不符合要求,建议设置grub密码"   #不等于0
fi 

写一个简单的脚本测试,如:写一个只有root用户才能执行的脚本,其他用户则提示指定内容后exit退出当前脚本
在这里插入图片描述

shell的变量:

变量是可变的值

本地变量:

变量名=值
注:
1、变量名可以包含_,数字,大小写字母,但绝对不可以数字开头
2、=两边不能有空格
3、值,如果含有空格的话,要使用’ ’ 或者 " " 引起来
定义变量的时候,变量名前是不需要加$的。
在这里插入图片描述
特点:只能影响当前的shell ,不能影响子shell,关系图如下 (在子进程中定义永久变量(export) 只会影响子进程,不会影响父进程(bash进子进程,子进程中再bash便是子进程的子进程了)
echo $$查看当前进程id ,父进程id和 子进程id不一样
在这里插入图片描述
关于不同执行方式,执行环境也不同,可能是在父进程执行,也可能是在子进程执行,如
在这里插入图片描述
bash定义变量是不会影响 子进程,但export定义变量会影响子进程(也可以说 同步到子进程)如:
在这里插入图片描述
如:脚本中需要多次使用到一个较长的值,可以定义为变量,后面直接调用变量即可
在这里插入图片描述

  • env查看所有环境变量

环境变量:PATH,UID,PS…

变量引用:
在这里插入图片描述

查看环境变量:echo $PATH , exportdeclare -x
查看已定义的所有变量:set
删除变量:unset name
查看系统自带配置文件:cat /etc/profile

echo $UID- 查看当前用户uid
echo $USER- 查看当前用户
echo $HOME - 查看当前用户家目录
echo $PS1(数字1) - 查看提示符(如:[root@control ~]# ) 详细参考:https://blog.csdn.net/cuichongxin/article/details/103949335
echo $PS2- 换行提示符
echo $PATH(很重要)- 当我们执行命令的时候,一定要指定这个命令的路径,如果没有写路径,则会到PATH里 所规定的的路径里 进行查询。详细参考:https://blog.csdn.net/cuichongxin/article/details/103950519
在字符界面登陆终端的时候,首先会运行家目录下面的一个隐藏文件: .bash_profile位置变量。
预定义变量:双引号—> 是能够解析双引号里特殊字符的 单引号—>忽略单引号里所有的特殊字符 —>相当于$0

位置变量: $0 $1 $2 … $[10] $# #*

位置变量 主要是向脚本中传递数据。
set命令作用主要是显示系统中已经存在的shell变量,以及设置shell变量的新变量值。set命令不能够定义新的shell变量。如果要定义新的变量,可以使用declare命令以变量名=值的格式进行定义即可。

  • $? 判断上一个命令执行成功返回0 否则返回1
  • $n 调用参数,前提是得先定义参数n
    +$0 代表命令本身,$1-9代表接受的第1-9个参数,10以上需要用{}括起来,括号中的就是变量,比如${10}代表接收的第10个参数,如果不加{},会以为是$1+后面的参数
  • $* 代表接收所有的参数,将所有参数看作一个整体
  • $@ 代表接收的所有参数,将每个参数区别对待
  • $# 代表接收的参数个数

测试,10以上需要用{}括起来,比如${10}代表接收的第10个参数,如果不加{},会以为是$1+后面的参数
在这里插入图片描述
比如说,我定义一个aa为book,花了10美元($10),这时不加{}的效果和加{}的效果如下
在这里插入图片描述

更加直观的看出 {} 的区别,现在定义一个dir为/root/目录,然后再次使用dir

在这里插入图片描述

$@$#的区别在于,比如有4个值,使用#@会循环4次,如果使用$#只循环一次(会将所有参数看作一个整体),如下

#!/bin/bash

echo "\s* 效果为 : "
for i in "$*"
        do
                echo $i
        done

echo "\s@ 效果为 : "
for j in "$@"
        do
                echo $j
        done

在这里插入图片描述

说一下位置路径中的basenamedirname的使用
在这里插入图片描述
basename可以用于,脚本中读取 $0的文件名称,因为$0也是脚本名称 加上basename后便看不到路径了 : basename $0即可

  • 测试1,位置变量的使用规则测试
#!/bin/bash

echo "脚本的名字是 `basename $0`"
echo "输入的第一个参数是 $1"
echo "输入的第二个参数是 $2"
echo "输入的第三个参数是 $3"
echo "一共输入了 $# 个参数,分别为 $*"

在这里插入图片描述

  • 测试2,写一个自定义用户 查询当前系统中是否存在
#!/bin/bash

if [ $# -eq 0 ] ; then
        echo "请加上需要查询的用户名参数"
        exit 1
fi

grep -q $1 /etc/passwd

if [ $? -eq 0 ] ; then
        echo "$1 用户是存在的"
else
        echo "$1 用户不存在"
fi
 

在这里插入图片描述

测试:
在这里插入图片描述

符号,运算符,条件判断

常见的几个符号: > >> ; | &&

>重定向
>>不会覆盖原有内容 的重定向
; 一行 执行多条命令分隔符
|管道符
&& 与: 前面的命令执行成功,后面的命令才会执行
||非:前面的命令执行失败,后面的命令才会执行
2>/dev/null 错误输出到 指定文件
1>/dev null 正确输出到 指定文件

常见运算符

秒变计算器的运算符 expr 仅支持整数
在这里插入图片描述
加:expr 12 + 12
减:expr 12 - 12
乘:expr 12 * 12
除:expr 12 / 12
求余:expr 12 % 12
平方:expr 12 ** 12
在这里插入图片描述
科学计算器: bc 注:如果没安装bc命令,可直接用yum安装:yum install -y bc
bc计算器保留多少位小数可以通过scale定义,但是scale只对除法、取余数、乘幂 有效;其他可用除1方法来实现scale功能; 如保留2位数 scale=2;
在这里插入图片描述
方法一: 直接输入命令bc 进入计算器模式
在这里插入图片描述
方法二: 使用echo 定义参数 用管道符 来输出结果:
在这里插入图片描述

常见的条件判断(对比)

连接符

&&(与) ||(或)
连接符一般需要判断2个条件,1:整体上是真还是假 2:当判断1完成后,是否要进行判断2
判断1 &&(或) 判断2 :两边为真则真 ($?返回值是0),如果判断1为真,执行判断2, 判断2为假 则整体为假 ,如果判断1为假,则不执行判断2
判断1 ||(非) 判断2 :一边为真则整体为真,如果判断1为真 则不执行判断2 ,如果判断1为假($?返回值不为0)则执行判断2,判断2为假 则整体为假

在这里插入图片描述

文件属性

  • 表达式
    文件(夹)或者路径;
    -e 目标是否存在(exist)
    -d 是否为路径(文件)(directory)
    -f 是否为文件 (file)
    -r 是否有读取权限(read)
    -w 是否有写入权限(write)
    -x 是否有执行权限 (excute)
    -l是否有软连接
    -e是否有block
    -z:判断制定的变量是否存在值
    -L:判断制定的是否为符号链接
    -s:判断存在的对象长度是否为0
    在这里插入图片描述

数字:

-eq等于 (equal)
-ne 不等于(not equal)
-gt 大于(greater than)
-lt 小于 (lesser than)
-ge 大于或者等于(greater or equal)
-le小于或者等于(lesser or equal)
在这里插入图片描述

小数(浮点型):Bash中常用的letexpr仅支持整数运算,不支持浮点数计算。要实现浮点数计算,可以使用bc或awk。
在这里插入图片描述

字符串:

字符串(字母)比较其实是自动转换为ASCII码的,虽然比较的是字母,其实系统看到的也是其字母对应的ASCII码而已,如a的ASCII码是97,b就是98

== 相等
!= 不相等
> 大于
>=大于等于
< 小于
<= 小于等于
[]是 不识别通配符的,[[]]识别通配符
注: 如果是等于需要使用正则,建议使用: =~ 而非==

在这里插入图片描述

一个简单的判断数值相等与否的shell:

#! /bin/bash
#判断用户输入的两个数是否相等
#ccx
if [ $1 -eq $2 ]then
echo "$1 等于 $2"
else
echo :$1 不等于 $2"
fi

 

在这里插入图片描述
创建用户输入的名称 文件:

#! /bin/bash
#创建用户输入的名称 文件
touch $1
if [ $? -eq 0 ] ; then
# 返回0 代表 执行成功 与之相反;
echo "$1 创建成功"
fi
echo "请输入需要创建的文件名称"

在这里插入图片描述
换行:echo -e "\n"

返回0 代表 执行成功 与之相反;

read(用户交互)

顾名思义 read 就是需要用户输入值 比如用于输入密码之类的
原理:read 默认有一个值$REPLY,即使单独单独输入read不调用值回车 也会让你输入值
在这里插入图片描述
read命令: 先后顺序t、n、s、p
语法 :read -p “请您输入密码:”
-p:给出提示符,默认不支持“\n”换行 需要echo -e “\n” 实现
-s:隐藏输入的内容
-t:给出等待时间
-n:限制读取字符的个数,触发到临界值会自动执行;
在这里插入图片描述

如:现在写一个 根据你输入的年龄判断 该年龄属于什么阶段,并且输入非数字时会提示你输入数字
在这里插入图片描述

#!/bin/bash

#echo -n "请输入一个年龄"
#read age

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

[[ $age =~ ^[0-9]+$ ]]
if [ $? -ne 0 ]  ; then
        echo "请输入一个数字"
        exit 1
fi

if [ $age -gt 120 ] || [ $age -lt 0 ] ; then
        echo "请输入一个合法的年龄"
elif [ $age -ge 60 ] && [ $age -lt 120 ] ; then
        echo "该年龄为老年人"
elif [ $age -ge 18 ] && [ $age -lt 60 ] ; then
        echo "该年龄为成年人"
else
        echo "未成年"
fi

脚本输出上色:

语法:echo -e "\033[字背景颜色;字体颜色;特效m字符串\033[关闭属性"
注:以下中文字部分 可以替换任何内容
#字体色差范围:30-37

echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"

#字背景颜色范围:40-47

echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;30m 红底黑字 \033[0m"
echo -e "\033[42;34m 绿底蓝字 \033[0m"
echo -e "\033[43;34m 黄底蓝字 \033[0m"
echo -e "\033[44;30m 蓝底黑字 \033[0m"
echo -e "\033[45;30m 紫底黑字 \033[0m"
echo -e "\033[46;30m 天蓝底黑字 \033[0m"
echo -e "\033[47;34m 白底蓝字 \033[0m"

#特效范围: 如果[后面的0m 加上了特效 那么后面这特效会一直执行 需要手动改回0m后特效才会停止;

echo -e "\033[0m 无任何特效 \033[0m"
echo -e "\033[1m 高亮度 \033[0m"
echo -e "\033[4m 下划线 \033[0m"
echo -e "\033[5m 闪烁 \033[0m"

注:混合使用需要使用``扩起来:

read -t 5 -n 5 -s -p "`echo -e "\033[32;5m 请输入您的密码: \033[5m"`"  pass

这样就会闪烁了 否则会失效:

处理海量数据的grep、cut、awk、sed 命令

简介:grep、cut、awk、sed 常常应用在查找日志、数据、输出结果等等,并对我们想要的数据进行提取,通常grep,sed命令是对行(hang)进行提取,cut和awk是对列进行提取

处理海量数据之grep命令:

grep应用场景: 通常对数据进行 行的提取
语法:grep [选项] …[内容]…[file]
-v #对内容进行取反提取(也就是忽略本身)
-n #对提取的内容显示行号
-w #精确匹配
-i #忽略大小写
^ #匹配开头行首
-E #正则匹配(等效egrep)
在这里插入图片描述

处理海量数据之cut命令:

cut应用场景:通常地数据进行列的提取
语法:cut [选项]…[file]

-d #指定分隔符
eg :为分隔符,截取出/etc/passwd的第一列跟第三列

cut -d ':' -f 1,3 /etc/passwd   #表示通过:截取 1和3列
cut -d ':' -f 1-3 /etc/passwd   #表示通过:截取 1到3列
cut -d ':' -f 2- /etc/passwd   #表示通过:截取 第二列到最后一列

在这里插入图片描述
-f #指定截取区域

cut -d ':' -f 1,3 /etc/passwd  注:不加-d 默认我制表符 文件必须+ -d 指明分隔符
 

在这里插入图片描述
本身为表的不需要加 -d
在这里插入图片描述
-c #以字符为单位进行分割
eg:截取/etc/passwd 文件第二个字符到第九个字符:

 cut -c 2-9 /etc/passwd

在这里插入图片描述
注:不加-d选项,默认为制表符,不是空格
eg:截取linux上面所有可登陆用户:
grep '/bin/bash' /etc/passwd在这里插入图片描述
只提取用户并且除去root用户:

grep '/bin/bash' /etc/passwd | cut -d ':' -f 1 | grep -v root 

在这里插入图片描述

处理海量数据之awk命令:

awk简介:其实一门编程语言,支持条件判断,数组,循环等功能,与grep,sed被称为linux三剑客,之所以叫awk是因为取其三位创始人的 family name 首字符
awk的应用场景:通常对数据进行列的提取;
语法:

awk '条件{执行 动作}' 文件名
awk '条件1{执行动作}条件2{执行动作}... ' 文件名
awk [选项] '条件1{执行动作}条件2{执行动作}... ' 文件名
特殊要点举例说明:
printf 不换行:格式printf("", ) 其中括号可省略,其中格式化字符串包括两部分内容: 
一部分是正常字符, 这些字符将按原样输出 printf("", ); 另一部分是格式化规定字符,
 以"%"开始printf("%.", ), 后跟一个或几个规定字符,用来确定输出内容格式。
 (%ns:字符串型,n代表有多少个字符;%ni:整型,n代表输出几个数字;
 %.nf:浮点型,n代表的是小数点后有多少个小数)

如:printf '%s\t%s\t%s\t%s\t%s\t%s\t\n' 1 2 3 4 5 6
在这里插入图片描述
print #打印出内容,默认会自动换行
\t #制表符
\n #换行符

eg:df -h | grep /dev/sda1|awk '{printf "/dev/sda1的使用率是:"} {print $5} '      

提取df -h 命令 中 /dev/sda1中的使用率
在这里插入图片描述
小数:echo "scale=2; 0.13+0.1" | bc | awk '{printf "%.2f\n",$0}'
scale定义保留2位小数,通过bc计算,但bc如果首位是0则不会显示0. 这时候通过printf 来显示0,2f代表后面保留2位小数 ,$0表示输出一整列;科学计算中print格式:(printf “%.”, )
在这里插入图片描述
$0#代表第一列
$1 #代表第二列
$2 #代表第三列

eg:df -h | grep /dev/sda1| awk '{print $5}' 

在这里插入图片描述
-F #指定分隔符

eg : cat /etc/passwd | awk -F":" '{print $1}'

使用:为分隔符,取passwd中的第一行
在这里插入图片描述
BEGIN #在读取所有行内容前就开始执行,常常被用于修改内置变量的值
FS #BEGIN时定义分隔符

eg:cat /etc/passwd |awk 'BEGIN {FS=":"} {print $1}' 

在这里插入图片描述
END #结束的时候 执行
NR #行号

eg:df -h |awk 'NR==2 {print $5}'

显示多行内容:df -h |awk 'NR>=1 && NR<=3 {print $1,$2}'
在这里插入图片描述

eg:awk '(NR>=20 && NR<=30) {print $1} ' /etc/passwd
在这里插入图片描述

处理海量数据之sed命令:

sed的应用场景:主要对数据进行处理(选取,新增,替换,删除,搜索)
sed语法:sed [选项] [动作] 文件名
常见的选项与参数:
-n#吧匹配到的行输出打印到屏幕
p#以行为单位进行查询,通常与-n一起使用
如:df -h | sed -n '2p'
在这里插入图片描述
d#删除
如:df -h |sed '2d'注:这种只删除内容 并不对源文件做改变,更改源文件需在sed后加 -i
在这里插入图片描述
a#在行的下面插入新的内容
如:在第二行下面插入新的内容:sed '2a test yes !!!' df .txt,注:这操作并不对源文件做出改变,更改源文件需在sed后加 -i
在这里插入图片描述
i#在行的上面插入新的内容
如:在第二行上面插入新的内容:sed '2a test yes !!!' df .txt,注:这操作并不对源文件做出改变,更改源文件需在sed后加 -i
在这里插入图片描述
c #替换
如:把第二行的内容替换为 test yes!!!:sed '2c test yes!!!' df.txt注:这操作并不对源文件做出改变 ,更改源文件需在sed后加 -i
在这里插入图片描述
s/ 要被取代的内容/新的字符串/g #指定内容进行替换
如:吧df.txt文件中的0%替换为100%: sed 's/0%/100%/g' df.txt注:该操作不会对原文件作出改变,更改源文件需在sed后加 -i
在这里插入图片描述
-i #对源文件进行修改 高危操作:修改前对原文件备份
如:吧df.txt文件中的0%替换为100%: sed -i 's/0%/100%/g' df.txt
在这里插入图片描述
搜索:在文件中搜索内容
如:查找df.txt文件里100%的条目 -n 显示 ,p 查询:2种表达方式
在这里插入图片描述
-e#表示可以执行多条动作
sed -i -e '1a #你说一切都是没想好' df.txt -i -e '3a #得到得和想要的对不上号' df.txt -i -e 's/100%/0%/g' df.txt注:每一次-e 前面的都会重新跑一遍;
在这里插入图片描述

cat << EOF 使用

这个其实就是一个可以自定义的注释信息,简单来说 就是 用于脚本开头解释
语法:cat << EOF
其中EOF可以替换为任意字符,但开头和结尾必须一致
这儿就可以自定义 信息了 这儿定义什么 屏幕上就会打印什么
也可以用这方法快速写入内容到文件:cat >> file << EOF
EOF
在这里插入图片描述
这个单独用于打印屏幕上 没什么意义,但可以用于写入 文本中和在脚本中使用,如写入文本:
在这里插入图片描述

以脚本为例:这就是一个手动执行的脚本,如下图,如果想了解该脚本,参考:https://blog.csdn.net/cuichongxin/article/details/101759690
在这里插入图片描述
看看执行效果,因为我加了while ,所以每一次操作都会显示该内容
在这里插入图片描述

循环控制语句if、for、case、while

if

if循环控制(单分支与多分支):
单分支1:

if [条件判断];then
	执行动作
fi

单分支2:条件成立执行动作1,否则执行动作2

if [条件判断];then
	执行动作1
else
	执行动作2
fi

如:判断111.txt文件是否存在,不存在则创建,并写入内容

!#/bin/bash
#。。。。
#ccx
if [ -e 111.txt ]; then
        echo '111.txt存在'
else
        echo '111.txt不存在,现已为您创建111.txt文本'
        touch 111.txt
        echo '并且该内容写入进了111.txt文本中'
        echo '并且该内容写入进了111.txt文本中' > 111.txt
        cat 111.txt
fi

在这里插入图片描述

也可以改成用户输入文件判断并创建: 注:if [ -e $1 ]是想对路径 可写成绝对路径 如 /etc/$1

!#/bin/bash

if [ -e $1 ];
        then 
        echo $1'存在'
else
        echo $1'不存在,现已为您创建'$1
        touch $1
        echo '并且该内容写入进了'$1'文本中'
        echo '并且该内容写入进了'$1'文本中' > $1
        cat $1
fi
 

在这里插入图片描述
多个判断(多分支循环);

if [条件判断]then
	执行动作
elif [条件判断];then
	执行动作
elif [条件判断];then
执行动作
		…
fi

在这里插入图片描述

for循环控制

(1)

for 变量名 in 值1 值2 值3
	do
	执行动作
	命令1,$变量名
	….
done

如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
在这里插入图片描述
(2)

for 变量名 in `命令`
	do
	执行动作
done

如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
seq –w(补0) 直接 seq –w 1 10 即可
在这里插入图片描述
其实可以利用利用该方法来批量建用户之类的
在这里插入图片描述
也可以使用正则,如列出某目录下所有以.d结尾的文件
在这里插入图片描述

(3)

for ((条件))
	do
	执行动作
done

如:每隔1秒打印一次1-10的循环条件 sleep睡眠命令
在这里插入图片描述

循环控制语句:break ,continue

break是满足条件跳出循环
continue提前结束本次循环而开始进行下一轮(跳出满足条件的条件)

做一个break的测试(命令要放在break之前,也就是先执行后判断)
在这里插入图片描述
做一个continue的测试(命令要放在continue之后,也就是先判断后执行)
在这里插入图片描述
来一个多次循环嵌套的说明一下(这是正常的循环)
在这里插入图片描述
加一个brack试试
在这里插入图片描述
在这里插入图片描述

case循环控制

应用场景:case循环常用语多重分支,与if不同的是,if可以判断多个条件,case只能判断一种条件
语法结构:

case 变量 in
	'值1')
		执行动作
;;

	'值2')
		执行动作
;;

	'值3')
		执行动作
;;

	...
esac

如:现在写一个 连接光盘的脚本
在这里插入图片描述

	#!/bin/bash

cat << !!
********************************************
*  这是一个询问脚本                        *
********************************************
!!

read -p "请问是否已经吧光盘连接起来了?(y/n):" say
case $say in
        y|Y)
			#该处放输入y以后需要执行的命令
			#如 mount ......
                ;;
        n|N)
                echo "请先吧光盘连接上去"
                exit 1
                ;;
        *)
                echo "只能输入y/n!!!"
                exit 1
esac

while 循环

普通while循环使用

应用场景:while 循环是条件循环也是不定循环,只要条件判断式成立,循环就会一直进行着,直到判断式不成立 或者 选择跳出循环 才会结束;也就是说 每次执行完do和done之间的语句,会再次到while后面的条件进行对比,如果城里,再次执行do和done之间的语句。

while [ 条件判断式 ]
	do
	执行动作
done

在这里插入图片描述
写一个遍历1-10的数 自动跳过第4个
在这里插入图片描述

while循环之read使用

语法:

while read 变量名 ; do
	执行动作
done < 读取文件

说一下执行读取读取文件的操作
遍历之前先来说一下,read,这个平常是用来接收用户输入的值的,当然也可以读取文件中的值,只是 单独使用read读取某文件的值 只能读取第一行
在这里插入图片描述
如果用read纪录/etc/passwd全部文件,就需要用到while
在这里插入图片描述

while也可以用来读取某个某个文件的值 而做下一步操作,比如 把一堆ip写在一个文件中(注意 必须一行一个ip) 批量ping 或者啥的, 也或者 把 一堆用户名写在一个文件里 批量建用户, 现在测试批量建用户
在这里插入图片描述

实现wc –l这个功能,后面必须跟上一个文本本间,来统计这个文件的行数
declare
declaretypeset内建命令(它们是完全相同的)可以用来限定变量的属性.这是在某些编程语言中使用的定义类型不严格的方式。命令declare是bash版本2之后才有的。命令typeset也可以在ksh脚本中运行。 -i 整数
在这里插入图片描述

#!/bin/bash

if [ $# -eq 0 ] ; then
        echo "请输入一个参数"
        exit 1
fi

declare -i num=0

while read aa ;do 
        let num=$num+1
done < $1
echo "${num}$1"

while循环之死循环妙用

死循环 顾名思义 就是循环一直存在 直到手动取消
语法有3种:

  • 1、
while true ; do
	执行语句
done
  • 2、
while ((1)) ; do
	执行语句
done
  • 3、
while : ; do
	执行语句
done

有时候需要while一直循环下去(死循环)
比如说 某个服务 有时候会自动停止,我们不知道,但如果使用while语句一直检测,某服务,如果检测停止后 就自动 start 启动, 先说明一下,如果查看服务是启动的 返回值是0 如果不是启动的 返回结果则非0 (谨慎用死循环,非要用,建议加上sleep)
在这里插入图片描述
现在以http 服务 为例,写一个脚本自动检测 该服务是否是active,如果不是 则自动start启动该服务,运行时 sh 脚本名称 > /dev/null & 最下面有说明 为什么这么执行以及执行后如果停止。
在这里插入图片描述

#!/bin/bash

while true ; do
        systemctl is-active httpd
		# 一般建议在这加上sleep 1 ——1秒钟检测一次
        if [ $? -ne 0 ] ; then
                systemctl start httpd
        fi
done

如果不吧输出结果 放到/dev/null 和放在后台执行后结果
在这里插入图片描述

放到后台以后,jobs 查看 后台进程 kill -9 %1杀死该进程 (一定要加%,否则杀死的是进程id为1的进程)
在这里插入图片描述

until循环

until循环和 while循环 相反,while是满足条件条件后执行 ,rntil是不满足条件后执行
语法:

until 条件 ; do
	执行命令
done

如:
let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
deckare 是定义变量类型,-i 是整数
在这里插入图片描述
对until这种反人类语法 感兴趣的就自己去深究一下

函数/库

函数

就是一个功能模块,调用这个函数的时候,就可以直接调用这个功能了,不需要再次重复写代码。
函数不引用是不执行的,并且只能再同一个脚本里重复引用,其他脚本里不能引用该函数
语法有3种:

  • 1、
 function 函数名(){
		…….执行命令
		}
  • 2、
function 函数名{
		……执行命令
		}

来一个简单的使用规则
在这里插入图片描述

#!/bin/bash

function x1 () {
        date
}

x1
x1
x1

稍微复杂一点的,下图脚本中:x1 $2 $1 确定了x1函数调用的参数是$2,而后面的$1是没有意义的(代码块只使用到了,$1)。
所以执行过程中$2(/etc/hosts)就是脚本中函数调用函数结果,而$1(/etc/passwd)没有意义。 在这里插入图片描述

#!/bin/bash

function x1 () {
        declare -i num=0
        while read aa ; do
                let num=$num+1
        done < $1
        echo "${num}$1"

}

函数是只能在自己脚本中使用,如果想在其他脚本中使用,就得使用库。
语法:

库名 (){
	….执行命令
}

另外一个文件 直接. 文件名(如果不在统一目录,需要用绝对路径) 即可调用

在这里插入图片描述

调用

调用死参数意义不大,但可以这么实现,死参数可以替换为灵活的,比如用户输入的 $1 $2 等等。了解就行,一般脚本用到的几率不高!
在这里插入图片描述

相关推荐
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页