shell脚本
面向过程语言
-
做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如果出现了情况B,做什么处理
-
问题规模小,可以步骤化,按部就班处理
-
以指令为中心,数据服务于指令
-
C,shell
面向对象语言
-
将编程看成是一个事物,对外界来说,事物是直接使用的,不用关心事物内部的情况。而编程就是设置事物能够完成功能。
-
一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
-
类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
-
对象是类的具象,是一个实体
-
问题规模大,复杂系统
-
以数据为中心,指令服务于数据
1.shell脚本基础
1.1 shell的作用
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当 了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执 行的操作传递给内核执行,并输出执行结果。 常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符 等方面会存在一些区别。通过/etc/shells 文件可以了解当前系统所支持的 Shell 脚本种类。
查看本机的shell信息
[root@localhost ~]# cat /etc/shells //查看当前系统支持的shell
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
[root@localhost ~]#
linux中常见的shell
-
bash:基于gun的框架下发展的shell
-
csh:类似c语言的shell
-
tcsh:整合了csh提供了更多功能
-
sh:已经被bash替换
-
nologin:让用户无法登录
bash (/bin/bash)是目前大多数Linux 版本采用的默认shell
1.2 什么是shell脚本?及构成
-
就是将命令按顺序一一列出,最后自动执行
-
执行需要权限,也可以直接使用绝对路径
-
脚本其实不复杂,通用脚本环境改变后依然可以使用的脚本
构成
-
脚本申明(解释器):第一行开头“#!/bin/bash”,表示此行以下的代码语句是通过/bin/bash程序来解释执行。#!/bin/bash为默认的解释器还有其他类型的解释器,#!/bin/python #!/bin/expect
-
注释信息:以#开头的语句表示为注释信息
-
可执行语句:比如echo命令用于输出“ ”之间的字符串
1.3脚本执行逻辑及执行方式
脚本执行逻辑
-
顺序执行:程序按从上到下顺序执行
-
选择执行:程序执行过程中,根据条件的不同,进行选择不同分支继续执行
-
循环执行:程序执行过程中需要重复执行多次某段语句
执行方式
-
指定路径去执行文件(需要有执行权限)
[root@localhost ~]# chmod +x gy.sh 加权限
指定相对路径.gy.sh
指定绝对路径/root/gy.sh
[root@localhost ~]# vim gy.sh
[root@localhost ~]# cat gy.sh
#!/bin/bash
ls /opt
[root@localhost ~]# . gy.sh
-bash: ./gy.sh: 权限不够
[root@localhost ~]# pwd gy.sh
/root
[root@localhost ~]# /root/gy.sh
-bash: /root/gy.sh: 权限不够
[root@localhost ~]# ll gy.sh
-rw-r--r--. 1 root root 20 8月 9 18:42 gy.sh
[root@localhost ~]# chmod +x gy.sh
[root@localhost ~]# ll gy.sh
-rwxr-xr-x. 1 root root 20 8月 9 18:42 gy.sh
[root@localhost ~]# ./gy.sh
passwd rh
[root@localhost ~]# /root/gy.sh
passwd rh
[root@localhost ~]#
2.指定解释器去执行(不需要权限)
[root@localhost ~]# bash gy.sh
passwd rh
指定了使用 bash去执行脚本不需要权限
2.1用bash去执行脚本 会新开一个bash去执行执行完后后自动退出
[root@localhost ~]# vim gy.sh
[root@localhost ~]# cat gy.sh
#!/bin/bash
ping 192.168.1.100
cd /etc
ls /opt
[root@localhost ~]# bash gy.sh
PING 192.168.1.100 (192.168.1.100) 56(84) bytes of data.
From 192.168.1.200 icmp_seq=2 Destination Host Unreachable
From 192.168.1.200 icmp_seq=3 Destination Host Unreachable
From 192.168.1.200 icmp_seq=4 Destination Host Unreachable
#后面还有很多linux默认长ping
这时候打开一个新的页面 发现有三个bash一个本来的bash,一个编译脚本的bash,一个是新开页面的bash
[root@localhost ~]# pstree -p |grep bash
|-sshd(1098)-+-sshd(56381)---bash(56387)---bash(57314)---p
| |-sshd(57397)---bash(57404)-+-grep(57456)
结束长ping
在新开页面查看
现在剩两个bash
[root@localhost ~]# pstree -p |grep bash
|-sshd(1098)-+-sshd(56381)---bash(56387)
| |-sshd(57397)---bash(57404)-+-grep(57459)
关闭新开页面
还剩一个bash
[root@localhost ~]# pstree -p |grep bash
|-sshd(1098)-+-sshd(56381)---bash(56387)-+-grep(57754)
source 相对,绝对 会影响你的当前目录
会影响你的当前目录
. /root/gy.sh
source /root/gy.sh
[root@localhost mnt]# cat /root/gy.sh
#!/bin/bash
cd /etc
ls /opt
[root@localhost mnt]# . /root/gy.sh
当前的目录位于: mnt
passwd rh
[root@localhost etc]# cd -
执行后位于:etc
[root@localhost mnt]# source /root/gy.sh
当前的目录位于: mnt
passwd rh
[root@localhost etc]#
执行后位于:etc
1.4 脚本错误调试
1.命令错误
命令出错不会影响接下来的命令继续
[root@localhost ~]# cat gy.sh
#!/bin/bash
cb /etc
ls /opt
[root@localhost ~]# ./gy.sh
./gy.sh:行2: cb: 未找到命令
passwd rh
#还是执行了ls /opt 这条命令
[root@localhost ~]# cd /opt/
[root@localhost opt]# ls
passwd rh
2.语法错误
会影响接下来的命令继续
-
逻辑错误
只能自己去筛查
查代码的正确
bash -n 脚本名称 (不在当前目录下加绝对路径) 检查语法错误
-n (noexec 或 no ecxecution 简称) - 指示 Shell 读取所有命令然而不执行它们,这个选项激活语法检查模式。
bash -x 脚本名称 (不在当前目录下加绝对路径) 逻辑错误
-x (xtrace 或 execution trace 简称) - 告诉 Shell 在终端显示所有执行的命令和它们的参数。 这个选项是启用 Shell 跟踪模式。
bash -x
bash -n
这里不存在语法错误
总结:脚本错误常见的有三种区别
-
语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的
-
命令错误,默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察
-
逻辑错误:只能使用 bash -x 进行
2 重定向与管道符
2.1重定向
类型 设备文件 文件描述编号 默认设备标准输入 /dev/stdin 0 键盘
标准输出 /dev/stdout 1 显示器
标准错误输出 /dev/stderr 2 显示器
交互式硬件设备
-
标准输入:从该设备接收用户输入的数据
-
标准输出:通过该设备向用户输出数据
-
标准错误:通过该设备报告执行出错信息
重定向的意思就是 ,不通过标准输出到屏幕上,输出到你指定的位置
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | 1> | 将输出结果保存到指定的文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 标准错误输出结果追加到指定的文件尾部 | |
混合输出 | &>无论对错都可以重定向 | 将标准输出、标准错误的内容保存到同一个文件中 |
例
重定向输入<
[root@localhost ~]# cat cs
2*3
[root@localhost ~]# bc < cs
6
重定向输出 1>
[root@localhost ~]# cat ml
123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123
[root@localhost ~]# cat ml 1>cs
[root@localhost ~]# cat cs
123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123
>>
[root@localhost ~]# cat ml
123
[root@localhost ~]# cat cs
456
[root@localhost ~]# cat cs >> ml
[root@localhost ~]# cat ml
123
456
标准错误输出2>
[root@localhost ~]# ls xxx
ls: 无法访问xxx: 没有那个文件或目录
[root@localhost ~]# ls xxx 2> cs
[root@localhost ~]# cat cs
ls: 无法访问xxx: 没有那个文件或目录
[root@localhost ~]#
2>>
[root@localhost ~]# cat ml
123
456
[root@localhost ~]# ls xxx 2>> ml
[root@localhost ~]# cat ml
123
456
ls: 无法访问xxx: 没有那个文件或目录
混合输出&>无论对错都可以重定向
[root@localhost ~]# ls xxx /opt &> cs [root@localhost ~]# cat cs ls: 无法访问xxx: 没有那个文件或目录 /opt: rh [root@localhost ~]# ls /opt/ rh
2.2 多行重定向
Here Document 概述 使用 I/O 重定向的方式将命令列表提供给交互式程序或命令,比如 ftp、cat 或 read 命令。 HereDocument是标准输入的一种替代品, 可以帮助脚本开发人员不必使用临时文件来构建输入信息, 而是直接就地生产出一个文件并用作命令的标准输入。
[root@localhost ~]# wc -l <<EOF > 123 > 123 > EOF 2
[root@localhost ~]#cat > ky15.txt #需要回车才会写入 hhh 111 ky15
[root@localhost ~]# cat >gy.txt <<EOF > 333 > 444 > 555 > EOF [root@localhost ~]# cat gy.txt 333 444 555 [root@localhost ~]# cat >>gy.txt <<EOF 333 444 555 EOF [root@localhost ~]# cat gy.txt 333 444 555 333 444 555
#####修改密码 [root@localhost data]#passwd zhangsan <<EOF > 123123 > 123123 > EOF > 更改用户 zhangsan 的密码 。 > 新的 密码:无效的密码: 密码少于 8 个字符 > 重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
###变量赋值 [root@localhost ~]# read a <<EOF > 1 > 2 > EOF [root@localhost ~]# echo $a 1 [root@localhost ~]# read a <<EOF <2 EOF [root@localhost ~]# echo $a <2
2.3管道符
管道符 |
将左侧的命令输出结果,作为右侧命令的输入(处理对象)可以 叠加使用
[root@localhost ~]# cp /etc/passwd /opt/ [root@localhost ~]# ls /opt/ passwd rh [root@localhost ~]# ls /opt/ |wc 2 2 10
[root@localhost opt]# echo "123123" |passwd --stdin zhangsan 更改用户 zhangsan 的密码 。 passwd:所有的身份验证令牌已经成功更新
3 变量
变量来源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念。
保存将来会变化的数据,即使数据变化,直接调用变量即可,各种 Shell 环境中都使用到了“变量”的概念。Shell 变量用来存放系统和用户需要使用的特定参数(值),而且这些参数可以根据用户的设定或系统环境的变化而相应变化。通过使用变量,Shell 程序能够提供更加灵活的功能,适应性更强。
3.1变量基础
常见 Shell 变量的类型包括:
自定义变量:由用户自己定义,修改和使用 环境变量:由系统维护,用于设置工作环境 只读变量:只可以读取不可以更改 位置变量:通过命令行给脚本传递参数 预定义变量:Bash中内置的一类变量,不能修改 有些规定好的变量 放在那里让你使用
系统内置变量:PATH,UID,HOSTNAME,USER
3.1.1 命名要求
-
区分大小写
-
不能使程序中的保留字和内置变量:如:if, for,hostname 命令 a=
-
只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
-
不要使用内置的变量,使用英文尽量使用词义通俗易懂,PATH
name='value' 变量名=变量值 直接字串:name='root' 变量引用:name="$USER" 命令引用:name=`COMMAND` 或者 name=$(COMMAND) 注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚本结束,也会自动删除
变量引用: $name ${name}
弱引用和强引用 "$name " 弱引用,其中的变量引用会被替换为变量值 '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
[root@localhost ~]# name=gy [root@localhost ~]# echo $name gy
[root@localhost ~]# ylc=123 [root@localhost ~]# echo $name$ylc gy123
[root@localhost ~]# echo ls
ls
[root@localhost ~]# echo $(ls)
anaconda-ks.cfg cs gy.sh gy.txt initial-setup-ks.cfg ml sysconf(1).sh
[root@localhost ~]# echo `ls`
anaconda-ks.cfg cs gy.sh gy.txt initial-setup-ks.cfg ml sysconf(1).sh
1.赋值时使用双引号(" ")可以直接调用变量
2.赋值时使用单引号(' ')$只会被认为是字符$ 不会调用变量
3.赋值时使用(``反撇在tab上面)命令替换,提取命令执行后的输出结 果 和$( ) 用法相同
4.{}可以分隔变量值
变量追加值
格式
变量名+=追加值
[root@localhost ~]# echo $name
gy
[root@localhost ~]# name+=:123
[root@localhost ~]# echo $name
gy:123
3.1.2 read -p
从键盘输入的内容变成变量
方法1 [root@localhost ~]# read -p "现在的时间是:" time 现在的时间是:10 [root@localhost ~]# echo $time 10 [root@localhost ~]# read -p "现在的时间是:" time 现在的时间是:12 [root@localhost ~]# echo $time 12 [root@localhost ~]#
方法2 [root@localhost opt]# vim 1.sh #!/bin/bash echo -n "请输入你的信息" read info echo $info [root@localhost ~]# bash 1.sh 请输入你的信息2 2 [root@localhost ~]#
3.1.3 变量作用范围
默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用。
可以通过内部命令export将指定的变量为全局变量,使用户定义的变量在所子shell环境中可以继续使用
方法:
方法:
-
格式1:export 变量名
-
格式2:export 变量名=变量值
可以使用pstree 查看shell的环境
输入bash进入子shell
ctrl+D组合exit 退出子shell
举例:
[root@localhost opt]# abc=123 [root@localhost opt]# echo $abc 123 [root@localhost opt]# bash [root@localhost opt]# echo $abc 为空 [root@localhost opt]# exit exit [root@localhost opt]# echo $abc 123 [root@localhost opt]# export abc #export 变量名 定义全局变量 [root@localhost opt]# bash [root@localhost opt]# echo $abc 123
3.1.4 整数的运算
expr只能进行整数的运算
格式: expr 变量1 运算符 变量2 [运算符 变量3]
运算符:
加法 +
减法 -
乘法 \ *
除法 /
取余 (取模)%
let
在Linux中,let
是一个用于执行算术操作的命令。它可以用于将一个算术表达式的结果赋值给一个变量。let
命令通常用于在shell脚本中进行简单的数学计算。
下面是一个示例,演示如何使用let
命令将两个变量相加并将结果赋值给一个新变量:
#!/bin/bash # 定义两个变量 num1=5 num2=10 # 使用let命令执行加法操作,并将结果赋值给sum变量 let "sum = num1 + num2" # 输出结果 echo "Sum: $sum"
当运行上述脚本时,它将计算5 + 10的结果,并将结果赋值给变量sum
。最后,脚本将输出结果Sum: 15
。
请注意,let
命令也可以用于执行其他算术操作,如减法、乘法和除法。它还支持使用变量和括号来编写复杂的算术表达式。你可以通过在终端中输入man let
来获取有关let
命令的更多详细信息。
#expr [root@localhost ~]#a=1 [root@localhost ~]#b=2 [root@localhost ~]#expr $a + $b #加减乘除前后有空格 3
随机数生成器变量:
$RANDOM 取值范围:0-32767 [root@localhost ~]#man bash $[RANDOM%33+1] [root@localhost ~]# echo $[RANDOM%34+1] 9 [root@localhost ~]#echo -e "\E[1;30mhello\E[0m" #颜色 [root@localhost ~]# echo -e "\E[1;$[RANDOM%7+31]mhello\E[0m" #随机颜色 [root@localhost ~]#echo $(expr $RANDOM % 33 + 1) #注意运算符附近都要有空格
3.2.1 环境变量
-
由系统提前创建,用来设置用户的工作环境
-
可以使用env查看环境变量
-
需要记住的常用环境变量
[root@localhost ftp]#env #可以看到所有
$USER 表示用户名称
$HOME 表示用户的宿主目录
$LANG 表示语言和字符集
$PWD 表示当前所在工作目录
$PATH 表示可执行用户程序的默认路径
环境变量:
-
可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
-
一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
-
一般只在系统配置文件中使用,在脚本中较少使用
2.3.2 只读变量
变量值不允许修改(重新赋值)的情况
无法使用 unset删除
最快方法重启
[root@localhost opt]# name=gy15 [root@localhost opt]# readonly name [root@localhost opt]# echo $name gy15 [root@localhost opt]# unset name bash: unset: name: 无法反设定: 只读 variable #只有退出进程 [root@localhost opt]# echo $name gy15 [root@localhost opt]# name=gy bash: name: 只读变量
2.3.3 位置变量
位置变量也称为位置参数,使用$1、$2、$3、…、$9 表示
[root@test1 ~]# vim 1.sh #!/bin/bash echo "$1" 位置1 echo "$2" 位置2 echo "${10}" 位置10 echo "$10" 位置1和0 echo "$*" 将所有项当成一个值 echo "$@" 所有项 echo "$0" 脚本自身 echo "$#" 后面参数的个数 [root@test1 ~]# ./1.sh {1..10} 1 2 10 10 1 2 3 4 5 6 7 8 9 10
$0 表示当前的脚本名称 [root@test1 ~]# vim weizhi.sh #!/bin/bash sum=`expr $1 + $2` echo "$1+$2=$sum" [root@test1 ~]# chmod +x weizhi.sh [root@test1 ~]# ./weizhi.sh 12 34 56 12+34=46 [root@test1 ~]#cat qiuhe.sh #!/bin/bash i=$1 m=$2 sum=0 let sum=$[i+m] echo $sum
2.3.4 预定义(状态)变量
系统帮你定义好了 拿来用就可以了,你不需要知道为什么,记住
-
$*:表示所有位置参数的内容看成一个整体返回 返回所有
-
$@:表示所有位置参数的内容分割成n份,每份作为一个独立的个体返回 返回所有
-
$?:表示前一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常
-
$#:表示命令行中位置参数的总个数
-
$0:表示当前执行的脚本或程序的名称 当前脚本的名字
-
$$:当前进程id
-
$!: 后台任务最后一个id
[root@localhost data]#bash test.sh {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@localhost data]#bash 1.sh {a..z}
at的结果是
a
[root@localhost data]#bash 2.sh {a..z}
星的结果是
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@localhost data]#cat 3.sh
#!/bin/bash
echo $1
[root@test1 ~]# vim 1.sh
#!/bin/bash
echo "$*" 将所有项当成一个值
echo "$@" 独立个体
echo "$#" 后面参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
将脚本1的结果 $@ 交给3 输出$1
将脚本2的结果 $* 交给3 输出$1
[root@localhost opt]# bash 1.sh 1 2 3
#!/bin/bash
echo "@结果"
./3.sh "$@"
[root@localhost opt]# cat 2.sh 1 2 3
#!/bin/bash
echo "*结果"
./3.sh "$*"
[root@localhost opt]# cat 3.sh
#!/bin/bash
echo "$1"
区别 $* 和 $@
#!/bin/bash
echo "打印出\$*"
for var in "$*"
do
echo "$var"
done
echo "打印出\$@"
for var in "$@"
do
echo "$var"
done
3.条件语句
test 测试文件的表达式 是否成立
格式1:test 条件表达式 格式2:[ 条件表达式 ] 注意[]空格,否则会失败 测试 是否成功使用 $? 返回值 [ 操作符 文件或目录 ] help test
操作符: -d:测试是否为目录(Directory) -e:测试目录或文件是否存在(Exist) -a:测试目录或文件是否存在(Exist) -f:测试是否为文件(File) -r:测试当前用户是否有权限读取(Read) -w:测试当前用户是否有权限写入(Write) -x:测试当前用户是否有权限执行(eXcute) -L: 测试是否为软连接文件
例子:
[root@test1 ~]# test -d /etc/sysconfig [root@test1 ~]# echo $? 0 [root@test1 ~]# test -f /etc/sysconfig [root@test1 ~]# echo $? 1 [root@test1 ~]# [ -d /etc/sysconfig/ ] 注意前后空格 [root@test1 ~]# echo $? 0
3.4.2比较整数数值
[ 整数1 操作符 整数2 ] 公式
-
-eq:第一个数等于(Equal)第二个数
-
-ne:第一个数不等于(Not Equal)第二个数
-
-gt:第一个数大于(Greater Than)第二个数
-
-lt:第一个数小于(Lesser Than)第二个数
-
-le:第一个数小于或等于(Lesser or Equal)第二个数
-
-ge:第一个数大于或等于(Greater or Equal)第二个数
[ 整数1 操作符 整数2 ] [root@test1 ~]# a=2 实例 [root@test1 ~]# b=3 [root@test1 ~] [ $a -eq $b ] [root@test1 ~]# echo $? 1 [root@test1 ~]# [ 2 -le 3 ] [root@test1 ~]# echo $? 0
3.4.3字符串比较
常用的测试操作符
-
=:字符串内容相同
-
!=:字符串内容不同,! 号表示相反的意思
-
-z:字符串内容为空
-
-n: 字符是否存在
格式
[ 字符串1 = 字符串2 ] 是否相同
[ 字符串1 != 字符串2 ] 是否不相同
[ -z 字符串 ] 是否为空
[ -n 字符串 ] 字符是否存在
[root@localhost data]#str1=wang [root@localhost data]#str2=zhou [root@localhost data]#[ $str1 = $str2 ] [root@localhost data]#echo $? 1 [root@localhost etc]# [ $USER = root ]&& echo true true [root@localhost etc]# [ $USER != root ]&& echo true
3.4.4逻辑测试(短路运算)
格式1:[ 表达式1 ] 操作符 [ 表达式2 ] ... 格式2:命令1 操作符 命令2 ...
常见条件
-
-a或&&:逻辑与,“而且”的意思全真才为真
-
-o或||:逻辑或,“或者”的意思一真即为真
-
!:逻辑否
(1)短路与 &&
CMD1 短路与 CMD2 && 同时满足命令1 和命令2 的要求 才会返回正确 全真才为真 一假即为假 第一个CMD1结果为真 ,第二个CMD2必须要参与运算,才能得到最终的结果 第一个CMD1结果为假 ,总的结果必定为假,因此不需要执行CMD2
(2)短路或 ||
CMD1 短路或 CMD2 一真即为真 第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2 第一个CMD1结果为假 (0),第二个CMD2 必须要参与运算,才能得到最终的结果
3.4.5 双中括号
[[ expression ]] 用法 == 左侧字符串是否和右侧的PATTERN相同 注意:此表达式用于[[ ]]中,PATTERN为通配符 =~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配 注意: 此表达式用于[[ ]]中;扩展的正则表达式
#通配符
[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#FILE=test.txt
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[[ "$FILE" != *.log ]]
[root@centos8 ~]#echo $?
0
3.4.6 () {}
(CMD1;CMD2;...)和 {空格CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行
[root@centos8 ~]#( cd /data;ls )
test.log
[root@centos8 ~]#pwd
/root
[root@centos8 ~]#{ cd /data;ls; }
test.log
[root@centos8 data]#pwd
/data
#()会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#( echo $BASHPID;sleep 100)
1979
[root@centos8 ~]#pstree -p
├─sshd(719)───sshd(1906)───sshd(1919)─┬─bash(1920)───bash(1979)───sleep(1980)
#{ } 不会开启子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#{ echo $BASHPID; }
1920
3.5 if语句的结构
3.5.1分支结构
单分支
if 判断条件;
then 条件为真的分支代码
fi
双分支
if 判断条件; then 条件为真的分支代码
else 条件为假的分支代码
fi
多分支
if 判断条件1 then 条件1为真的分支代码
elif 判断条件2 then 条件2为真的分支代码
elif 判断条件3;then 条件3为真的分支代码
... else 以上条件都为假的分支代码
fi
3.5.2 case
格式
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac case 变量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 默认分支 ;;
###
4.循环语句
echo命令
echo -n 表示不换行输出 echo -e 表示输出转义符 常用的转义符
选项 | 作用 |
---|---|
\r | 光标移至行首,并且不换行 |
\s | 当前shell的名称,如bash |
\t | 插入Tab键,制表符 |
\n | 输出换行 |
\f | 换行,但光标仍停留在原处 |
\ | 表示插入"\"本身转义 |
\b | 表示退格 不显示前一个字符 |
\c | 抑制更多的输出或不换行 |
[root@localhost ky15]#echo -e "12345\b678"
##退格删除前面的字符
1234678
[root@localhost ky15]#echo -e "12345\b\b678"
123678
[root@localhost ky15]#echo -e "12345\b\b\b678"
12678
[root@localhost ky15]#echo -e "12345\b\b\b\b678"
16785
###注意退格键和末尾的字符相关,超过末尾的字符数量 会出bug 了解即可
date
date查看当前系统时间
-d 你描述的日期,显示指定字符串所描述的时间,而非当前时间
%F 完整日期格式,等价于 %Y-%m-%d
% T 时间(24小时制)(hh:mm:ss)
[root@localhost ~]# date -d '-1 day' +%F
2021-10-21
[root@localhost ~]# date +%F
2021-08-19
[root@localhost ~]# date -d '1 day ' +%F-%T
2021-08-20-23:28:42
[root@localhost mnt]# date -d "-3 day" 前三天
日历 [root@localhost data]#cal 2021 #查看日历 [root@localhost data]#cal 9 1752 九月 1752 日 一 二 三 四 五 六 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
5.正则表达式 过滤文本
-
正则表达式:正则表达式是一种更复杂、更强大的模式匹配工具,可以用于文本处理和搜索。其语法包含了更多的元字符和特殊字符,例如
.
(匹配任意单个字符)、+
(匹配前面的元素一次或多次)、{}
(指定匹配次数范围)等。
与通配符的区别
-
正则表达式:正则表达式是一种更复杂、更强大的模式匹配工具,可以用于文本处理和搜索。其语法包含了更多的元字符和特殊字符,例如
.
(匹配任意单个字符)、+
(匹配前面的元素一次或多次)、{}
(指定匹配次数范围)等。
主要用来匹配字符串(命令结果,文本内容),
通配符匹配文件(而且是已存在的文件)
-
基本正则表达式
-
扩展正则表达式
可以使用
man 7 regex
可以使用 man手册帮助
5.1.1 元字符(字符匹配)
元字符:
. 匹配任意单个字符,可以是一个汉字
[] 匹配指定范围内的任意单个字符,示例:[zhou] [0-9] [] [a-zA-Z] [:alpha:]
[^] 匹配指定范围外的任意单个字符,示例:[^zhou] [^a.z] [a.z]
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符(水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围
广
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
\w #匹配单词构成部分,等价于[_[:alnum:]]
\W #匹配非单词构成部分,等价于[^_[:alnum:]]
\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意
Unicode 正则表达式会匹配全角空格符
元字符点(.)
[root@localhost ~]#ls /etc/|grep rc[.0-6] #此处的点代表字符 rc0.d rc1.d rc2.d rc3.d
5.1.2 表示次数
-
#匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配 .* #任意长度的任意字符,不包括0次 \? #匹配其前面的字符出现0次或1次,即:可有可无 + #匹配其前面的字符出现最少1次,即:肯定有且 >=1 次 {n} #匹配前面的字符n次 {m,n} #匹配前面的字符至少m次,至多n次 {,n} #匹配前面的字符至多n次,<=n {n,} #匹配前面的字符至少n次 ifconfig ens33|grep netmask|grep -o
[root@localhost ~]# echo google |grep 'go\{2\}gle'
#带表前面的o出现2次
[root@localhost ~]# echo gooooogle |grep 'go\{2,\}gle'
#带表前面的o出现2次以上
gooooogle
[root@localhost ~]# echo gooooogle |grep 'go\{2,5\}gle'
#带表前面的o出现2次以上5次以下
5.1.3位置锚定
^ #行首锚定, 用于模式的最左侧 $ #行尾锚定,用于模式的最右侧 ^PATTERN$ #用于模式匹配整行 (单独一行 只有root) ^$ #空行 ^[[:space:]]*$ # 空白行
< 或 \b #词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部) > 或 \b #词尾锚定,用于单词模式的右侧 <PATTERN> #匹配整个单词
5.1.4分组或其他
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
[root@localhost ~]#echo abccc |grep "abc\{3\}"
abccc
[root@localhost ~]#echo abcabcabc |grep "\(abc\)\{3\}"
#分组 匹配abc
abcabcabc
[root@localhost ~]#echo 1abc |grep "1\|2abc"
#只匹配了1
1abc
[root@localhost ~]#echo 1abc |grep "\(1\|2\)abc"
#1abc或者2abc
1abc
5.1.5 扩展正则表达式(表示字符相差不大)
grep -E
egrep
表示次数
* 匹配前面字符任意次 ? 0或1次 + 1次或多次 {n} 匹配n次 {m,n} 至少m,至多n次 {,n} #匹配前面的字符至多n次,<=n,n可以为0 {n,} #匹配前面的字符至少n次,<=n,n可以为0
表示分组
() 分组 分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+ 后向引用:\1, \2, ... | 或者 a|b #a或b C|cat #C或cat (C|c)at #Cat或cat
5.2 grep
grep [选项]… 查找条件 目标文件
-
-i:查找时忽略大小写
-
-v:反向查找,输出与查找条件不相符的行
-
-o 只显示匹配项
-
-f 对比两个文件的相同行
-
-c 匹配的行数([root@localhost ky15]# grep -c root passwd 2)
-E 使用ERE,相当于egrep
-F 不支持正则表达式,相当于fgrep
-f file 根据模式文件,处理两个文件相同内容 把第一个文件作为匹配条件
-r 递归目录,但不处理软链接
-R 递归目录,但处理软链接
6 AWK
gawk:模式扫描和处理语言,可以实现下面功能
vim: 是将整个文件加载到内存中 再进行编辑, 受限你的内存
awk(语言): 读取一行处理一行,
在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。而awk比较倾向于将一行分成多个字段然后进行处理。AWK信息的读入也是逐行
指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互
的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚
本,完成各种自动化配置任务。
工作原理:
前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
格式:
awk [options] 'program' var=value file…
awk 选项 模式 处理的动作 指定 '{print }'
-F 指定分隔符 -v 自定义变量 -f 脚本 awk [options] -f programfile var=value file…
#说明: program通常是被放在单引号中,并可以由三种部分组成 BEGIN语句块 模式匹配的通用语句块 END语句块
pattern{action statements;..} pattern:决定动作语句何时触发及触发事件,比如:BEGIN,END,正则表达式等 action statements:对数据进行处理,放在{}内指明,常见:print, printf
#常见选项: -F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符 -v(小v) var=value 变量赋值
awk [选项] '模式条件{操作}' 文件1 文件2....
awk -f|-v 脚本文件 文件1 文件2.....
6.1基础用法
print动作
[root@localhost ~]#awk ''
#什么都不写 空没有效果
[root@localhost ~]#awk '{print}'
##在打印一遍
dd
dd
[root@localhost ~]#awk '{print "hello"}'
#字符串需要添加双引号,单引号已被使用
1
hello
1
hello
[root@localhost ~]#awk '{print "hello"}' < /etc/passwd
[root@localhost ~]#ls | awk '{print "hello"}'
[root@localhost ~]#awk 'BEGIN{print 100+200}'
#运算
300
6.2awk 常见的内置变量
-
FS :指定每行文本的字段分隔符,缺省为空格或制表符(tab)。与 “-F”作用相同 -v "FS=:"
-
OFS:输出时的分隔符
-
NF:当前处理的行的字段个数
-
NR:当前处理的行的行号(序数)
-
$0:当前处理的行的整行内容
-
$n:当前处理行的第n个字段(第n列)
-
FILENAME:被处理的文件名
-
RS:行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是\n
########### FS #################
[root@localhost ky15]#awk -v FS=':' '{print $1FS$3}' /etc/passwd
#此处FS 相当于于变量 -v 变量赋值 相当于 指定: 为分隔符
[root@localhost ky15]#awk -F: '{print $1":"$3}' /etc/passwd
shell中的变量
[root@localhost ky15]#fs=":";awk -v FS=$fs '{print $1FS$3}' /etc/passwd
#定义变量传给FS
######### 支持变量 ##################
[root@localhost ky15]#fs=":";awk -v FS=$fs -v OFS="+" '{print $1,$3}' /etc/passwd
#输出分隔符
-F -FS一起使用 -F 的优先级高
6.3自定义变量
[root@localhost ~]#awk -v test='hello' 'BEGIN{print test}'
hello
awk -v test1=test2="hello" 'BEGIN{test1=test2="hello";print test1,test2}'
awk -v test='hello gawk' '{print test}' /etc/fstab
awk -v test='hello gawk' 'BEGIN{print test}'
awk 'BEGIN{test="hello,gawk";print test}'
awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
6.4 模式
awk '模式{处理动作}'
不支持使用行号,但是可以使用变量NR 间接指定行号
gender ###正则表达式 /pat1/
匹配pat1 的行
/pat1/,/pat2/ #正则表达式1 到正则表达式2 之间的行 如果匹配不到2的表达式 会一直匹配到文末
pat1 正则表达式1 pat2 正则表达式2
#模糊匹配,用~表示包含,!~表示不包含
取时间
####比较操作符: ==, !=, >, >=, <, <=
#####逻辑 与:&&,并且关系 或:||,或者关系 非:!,取反
标签:脚本,shell,gy,echo,sh,localhost,root,bash From: https://www.cnblogs.com/sl08/p/17627477.html