shell 脚本基础笔记(全)

shell 专栏收录该内容
38 篇文章 4 订阅

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 等等。了解就行,一般脚本用到的几率不高!
在这里插入图片描述

  • 4
    点赞
  • 2
    评论
  • 30
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
第1章 BashShell命令 6 1.1 Shell提示符 6 1.2 文件与目录Shell命令 7 1.2.1 更改目录命令(cd) 7 1.2.2 列表命令(ls) 7 1.2.3 操作文件命令 10 1.2.4 目录处理命令 14 1.2.5 查看文件内容命令 15 1.3 监控程序 20 1.3.1 进程查看 20 1.3.2 实时进程监控 22 1.3.3 停止进程 24 1.4 监控磁盘空间 25 1.4.1 挂载介质 25 1.4.2 使用df命令 26 1.4.3使用du命令 27 1.5 操作数据文件 28 1.5.1 数据排序(sort) 28 1.5.2 搜索数据 (grep) 30 1.5.3 压缩数据 30 1.5.4 归档数据(tar) 33 1.6 使用Linux环境变量 34 1.6.1 设置环境变量 34 1.6.2 默认的shell环境变量与path变量的设置 37 1.7 Linux文件权限 40 1.7.1 Linux安性 40 1.7.2 使用Linux用户组 46 1.7.3 解码文件权限 47 1.7.4 修改安设置 49 1.8 vim编辑器 52 第2章 基本脚本编译 54 2.1 创建脚本与使用变量 54 2.1.1 创建脚本 54 2.1.2 使用变量 55 2.2 重定向输入输出与数学计算 57 2.2.1 输出重定向 57 2.2.2 输入重定向 58 2.2.3 管道 58 2.2.4 数学计算 58 2.3 退出脚本 60 第3章 结构化命令 61 3.1 if语句 61 3.1.1 if-then语句 61 3.1.2 if-then-else语句 61 3.1.3 嵌套if语句 62 3.2 if条件语句 63 3.2.1 数值比较 63 3.2.2字符串比较 64 3.2.3 文件比较 65 3.2.4 复合条件检查 65 3.3 if-then的高级特征与case命令 66 3.3.1 使用双圆括号 66 3.3.2 使用双方括号 67 3.3.3 case命令 67 3.4 for命令 67 3.4.1 读取列表 68 3.4.2 读取变量与读取命令 69 3.4.3 改变字段分隔符与使用通配符读取目录 69 3.4.5 C式的for命令 70 3.5 while、until命令 71 3.5.1 使用多条测试命令 71 3.5.2 until命令与循环嵌套 72 3.6 文件数据的循环与控制循环 73 3.6.1 文件数据的循环 73 3.6.2 break命令 73 3.6.3 continue命令 75 第4章 处理用户输入与显示数据 76 4.1 命令行参数与特殊的参数变量 76 4.1.1 读取参数 76 4.1.2 读取程序名称 77 4.1.3 测试参数 77 4.1.4 参数计数 77 4.1.5 获取所有数据 78 4.2 移位与选项 79 4.2.1 移位 79 4.2.2 找出选项 79 4.2.3 使用getopt命令 81 4.2.4 更高级的getopts命令 83 4.2.4 标准化选项 84 4.3 获取用户输入 84 4.3.1 基本读取 84 4.3.2 计时 85 4.3.3 默读与文件读取 85 4.4 显示数据 86 4.4.1 标准文件描述符 86 4.4.2 重定向错误 87 4.4.3 临时重定向 88 4.4.4永久重定向 88 4.4.5 在脚本中重定向输入 89 4.5 创建自己的重定向 90 4.5.1 创建输出文件描述符 90 4.5.2 重定向文件描述符 90 4.5.3 创建输入文件描述符 91 4.5.4 创建读取/写入文件描述符 91 4.5.5 关闭文件描述符 92 4.5.6列出开发文件描述符 92 4.5.7禁止命令输出 94 4.6 使用临时文件 94 4.6.1 创建本地临时文件 94 4.6.2 在/temp中创建临时文件 95 4.6.3 创建临时目录 96 4.6.4 记录消息 96 第5章 脚本控制 97 5.1 处理信号 97 5.1.1 Linux信号回顾 97 5.1.2 生成信号 97 5.1.3捕获信号 99 5.1.4捕获脚本退出 99 5.1.4移除捕获 100 5.2 以后台模式运行脚本 100 5.3 作业控制 102 5.3.1查看作业 102 5.3.2重新启动停止的作业 103 5.4 nice与renice命令 104 5.4.1 nice命令 104 5.4.2 renice命令 104 5.5 定时运行脚本 105 5.5.1使用at命令调度作业 105 5.5.2使用batch命令调 107 5.5.3 调用定期脚本 107 5.6 从头开始 109 5.6.1在启动时启动脚本 109 5.6.2随新shell一起启动 109 第6章 创建函数 110 6.1 基本脚本函数 110 6.1.1 创建函数 110 6.1.2 使用函数 110 6.2 返回值 111 6.2.1 默认退出状态 111 6.2.2 使用return命令 111 6.2.3 使用函数输出 112 6.3 在函数中使用变量 112 6.3.1 向函数传递参数 112 6.3.2 在函数中处理变量 113 6.4 数组变量与函数 114 6.4.1 向函数传递数组 114 6.4.2从函数返回数组 115 6.5 函数递归与创建库 116 6.5.1函数递归 116 6.5.2 创建库 116 6.6 在命令行中使用函数 117 6.6.1在命令行创建函数 117 6.6.2在.bashrc文件中定义函数 117 6.7 select命令使用 119 第7章 sed、gawk介绍与正则表达式 120 7.1 sed编辑器 120 7.1.1 在命令行中定义编辑器命令 120 7.1.2 在命令行中使用多个编辑器命令 121 7.1.3 从文件读取编辑器命令 121 7.2 gawk程序 122 7.2.1 gawk命令格式 122 7.2.2 自命令行读取程序脚本 122 7.2.3 使用数据字段变量 123 7.2.4 在程序脚本中使用多个命令 124 7.2.5从文件读取程序 124 7.2.6 在处理数据之前运行脚本 125 7.2.7 在处理数据之后运行脚本 125 7.3 sed编辑器基础知识 126 7.3.1 更多替换选项 126 7.3.2 使用地址 127 7.3.3 删除行 128 7.3.4 插入和附加文本 129
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值