Linux-shell零基础入门到大师

Linux-shell零基础入门到大师

shell入门

一、shell概述

概述:
  • shell 是一个命令解释器,它接收应用程序,用户命令,然后调用系统操作内核。

  • 易编写、易调试、灵活性强

  • 查看当前系统解释器类型

  • shell就是人机交互的一个桥梁

  • shell的总类

[root@xiongbinbin test123]# cat /etc/shells
/bin/sh               # 是bash shell 的一个快捷方式
/bin/bash			 # bash shell 是大多数Linux 默认的shell,包含的功能几乎可以涵盖shell所有的功能
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
  • 查看当前shell
[root@xiongbinbin /]# echo $SHELL
/bin/bash
常用快捷键
  • 命令和文件自动补全
    • Tab只能补全命令和文件

常见快捷键

crtl +c		终止前台运行的程序
crtl +z		将前台运行的程序挂起到后台
crtl +d		退出,等价exit
crtl +l 	清屏
crtl +a |home 	光标移动到命令行的最前端
crtl +e |end 	光标移动到命令行的最后端
crtl +u		删除光标前所有的字符
crtl +k 	删除光标后所有的字符
crtl +r		搜索历史命令
  • test
test  shell中做判断
判断结果不输出,一般是用$?来根据执行结果判断真假

test 等价与[ ]

eg : test 1==1   等价于 [ 1==1 ]  # 注意中括号两端一定要有空格

test    &&  ||

[test123@xiongbinbin ~]$ test 1>3&& test$? -eq 0 echo '1大于3'||echo '1小于3'
1小于3
  • watch
watch 命令会以周期性的方式执行给定的命令,并全屏显示执行结果。
命令默认情况下每间隔 2 秒钟执行一次程序,可使用该参数指定间隔时间。

Usage:
watch [options] command
	-d : 高亮显示输出中不同的部分
	-g : 命令输出有变化时退出
	-e : 当命令运行返回非 0 时,则退出
	-n : watch 命令默认情况下每间隔 2 秒钟执行一次程序,可使用该参数指定间隔时间。
	-t : 会关闭 watch 命令在顶部显示的时间间隔、命令、当前时间输出等头部信息
	-x : 将命令传递给exec而不是“sh-c”;exec是用被执行的命令行替换掉当前的shell进程,且exec命令后的其他命令将不再执行。
  • 标准输入stdin、标准输出stdout 、标准错误输出stderr
0 : 标准输入
1 : 标准输出
2 : 标准错误输出
/dev/null : 可以将/dev/null看作"黑洞". 等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到
命令					标准输出		标准错误
> &2							 	输出到标准错误
> &1				 输出到标准输出
>/dev/null	2>&1		丢弃		  	丢弃
2>&1	>/dev/null		丢弃		  	屏幕
1>/dev/null				丢弃		  	屏幕
2>/dev/null				屏幕		  	丢弃

二、基础命令复习

2.1数据处理相关命令

2.1.1 数据检索
grep/egrep 行检索
grep: 负责从数据源中检索对应的字符串,进行行过滤。

egrep即扩展grep,等同于grep -E。可用于扩展正则表达式。

  • 语法:grep options “keys” filename
options:
  -i:不区分大小写
  -v:查找不包含指定内容的行,反向选择
  -w:按单词搜索
  -n:显示行号
  -A:显示匹配行,及其后面多少行
  -B:显示匹配行,及其前面多少行
  -C:显示匹配行,及其前后多少行
  
  -o:打印匹配关键字
  -c:统计匹配到的次数             
  -r:逐层遍历目录查找
  -l:只列出匹配的文件名
  -L:列出不匹配的文件名
  -E:使用扩展正则匹配
  -e:使用正则匹配
  ^key:	以关键字开头
  key$:以关键字结尾
  ^$:  匹配空行
  --color=auto:设置将匹配到的关键字部分加上颜色显示
  
  
  永久设置颜色:
  1)全局:
  vim /etc/bashrc
  alias grep='grep --color=auto'
  source /etc/bashrc
  2) 局部某个用户:
  vim ~/.bashrc
  alias grep='grep --color=auto'
  source /etc/bashrc
cut/tr 字符串检索
  • cut 数据截取
cut 用于列截取
-c:以字符为单位进行分割
-d:自定义分割符,默认为制表符:\t
-f:与-d一起使用,指定显示哪个区域。


cut -d: -f1 1.txt  以:冒号分割,截取第一列内容
cut -d: -f1,6,7 1.txt  以:冒号分割,截取第1,6,7列内容
cut -d: -f1-6 1.txt  以:冒号分割,截取第1-6列内容
cut -c4 1.txt  截取文件中每行第4个字符
cut -c1-4 1.txt  截取文件中每行的第1-4个字符
cut -c5-  1.txt  从第5个字符开始截取后面所有的字符

  • tr 字符转换:替换,删除
tr 用来从标准输入中通过替换或删除操作进行字符转换;主要用于删除文件中控制字符或进行字符转换。
使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。

语法:
替换:commands|tr 'string1' 'string2'
tr  'string1'  'string2'  < filename  # 将filename文件中的string1替换成string2; 且string2等额替换string1

删除:
tr options 'string1' < filename
	-d: 删除字符串1中所有输入字符。
	-s: 删除所有重复出现字符序列,只保留第一个;即将重复出现的字符串压缩为一个字符串。

	a-z : 任意小写
	A-Z : 任意大写
	0-9 : 任意数字
  • 示例
# 检索出 'inet' 行
[root@xiongbinbin test123]# ifconfig ens33|grep -w 'inet'
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.204.3  netmask 255.255.255.0  broadcast 192.168.204.255
        
# 对检索出的内容进行 替换去重空格后,截取,获取iPv4 地址
[root@xiongbinbin test123]# ifconfig ens33|grep -w 'inet'|tr -s ' ' |cut -d ' ' -f3
192.168.204.3

# 将上述获取到的内容再经过tr处理删除字符串中的'1'
[root@xiongbinbin test123]# ifconfig ens33|grep -w 'inet'|tr -s ' ' |cut -d ' ' -f3|tr -d 1
92.68.204.3

# 将上述获取到的内容再经过tr处理删除字符串中的'1-6'  可见其中的1、2、3、4、6都被删除了
[root@xiongbinbin test123]# ifconfig ens33|grep -w 'inet'|tr -s ' ' |cut -d ' ' -f3|tr -d [1-6]
9.8.0.
2.1.2 数据处理
sort 排序
sort: 将文件中的每一行作为一个单位,默认从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

语法:
sort [options] [filename]

-u : 去除重复行
-r : 降序排序,默认是升序
-o : 将排序结果输出到文件中  类似  重定向符号 >
-n : 以数字排序,默认是按字符排序
-t : 分隔符
-k : 第N列

-b : 忽略前导空格
-R : 随机排序,每次运行的结果均不同。
  • 示例
sort -n -t: -k3 1.txt	  # 以冒号分割,根据第三的内容按数字排序
sort -nr -t: -k3 1.txt    # 以冒号分割,根据第三的内容按数字降序排序
sort -n -t: -k4 -u 1.txt  # 以冒号分割,根据第四列的内容进行去重
sort -n 2.txt			 # 按数字排序
sort -nu 2.txt				
sort -nr 2.txt			  # 按数字降序排序
sort -nru 2.txt
sort -n 2.txt -o 3.txt	   # 按数字排序并将结果重定向到3.txt文件中
sort -R 2.txt			  # 随机排序
sort -u 2.txt
uniq 去除连续的重复行
  • 实现去重先要排序,即和 sort 结合使用
语法:
uniq [options] [filename]

-i : 忽略大小写
-c : 统计重复次数
-d : 只显示重复行
  • 示例
uniq 2.txt
uniq -d 2.txt
uniq -dc 2.txt
tee 双向输出
tee 工具从标准输入读取并写入标准输出和文件,即:双向覆盖重定向<屏幕输出|文本输入>

语法:
somecommand |tee 

-a : 双向追加重定向
  • 示例
echo hello world
echo hello world |tee file1
cat file1
echo 999|tee -a file1
cat file1

[root@xiongbinbin test123]# echo hello world
hello world
[root@xiongbinbin test123]# echo hello world |tee file1
hello world
[root@xiongbinbin test123]# ll
total 776
-rw-r--r-- 1 root root   2467 Nov  7 13:37 1.txt
-rw-r--r-- 1 root root     10 Nov  6 14:11 2.txt
-rw-r--r-- 1 root root     12 Nov  7 15:25 file1
-rw-r--r-- 1 root root 779692 Nov  5 21:51 wget-log
[root@xiongbinbin test123]# cat file1
hello world
[root@xiongbinbin test123]# echo 999|tee -a file1
999
[root@xiongbinbin test123]# cat file1
hello world
999
[root@xiongbinbin test123]#
paste 文本数据合并
paste工具用于合并文件行输出到屏幕,不会改动源文件

-d : 自定义分隔符,默认是tab,只接受一个字符
-s : 将每个文件中的所有内容按照一行输出,文件中的行与行以TAB间隔
  • 示例
[root@xiongbinbin test123]# cat a.txt
hello
[root@xiongbinbin test123]# cat b.txt
hello world
888
999
[root@xiongbinbin test123]# paste a.txt b.txt
hello   hello world
        888
        999
[root@xiongbinbin test123]# paste -d '@' a.txt b.txt
hello@hello world
@888
@999
[root@xiongbinbin test123]# paste -d '@' b.txt a.txt
hello world@hello
888@
999@
[root@xiongbinbin test123]# paste -s b.txt a.txt
hello world     888     999
hello
xargs 数据处理
  • xargs 上一个命令的输出作为下一个命令的命令行参数
  • 管道符(|): 上一个命令的输出作为下一个命令的输入,做的是数据源
xargs 可以将管道或者标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
xargs 一般是和管道一起使用。
===============================

命令格式:
"[somecommand]|[filename]" |xargs -item command

options:
-a file : 从文件中读入作为sdtin
-E flag : flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p : 当每次执行一个argument的时候询问一次用户。
-n num : 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是所有的。
-t : 表示先打印命令,然后再执行,即显示是怎么执行的
-i : 或者是 -I , 这得看Linux支持了,将xargs的每项名称,一般是一行一行复制给{},可以用{}代替。
-r : no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-d : delim分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。

  • 示例
[root@xiongbinbin test123]# find ./ -name 1.txt |xargs gzip
[root@xiongbinbin test123]# ll
total 784
-rw-r--r-- 1 root root    993 Nov  7 13:37 1.txt.gz
-rw-r--r-- 1 root root     10 Nov  6 14:11 2.txt
-rw-r--r-- 1 root root      6 Nov  7 15:42 a.txt

[root@xiongbinbin test123]# cat c.txt
1
2
3
4
5
6
7
8
9
10
[root@xiongbinbin test123]# xargs -a c.txt
1 2 3 4 5 6 7 8 9 10
[root@xiongbinbin test123]# xargs -a c.txt -E 5
1 2 3 4
[root@xiongbinbin test123]# xargs -a c.txt -p
echo 1 2 3 4 5 6 7 8 9 10 ?...y
1 2 3 4 5 6 7 8 9 10
[root@xiongbinbin test123]# xargs -a c.txt -n 3
1 2 3
4 5 6
7 8 9
10
[root@xiongbinbin test123]# xargs -a c.txt -n 3 -p
echo 1 2 3 ?...y
1 2 3
echo 4 5 6 ?...y
4 5 6
echo 7 8 9 ?...y
7 8 9
echo 10 ?...y
10
[root@xiongbinbin test123]# cat c.txt |xargs -t
echo 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10

  • **上述可以看出读入文件内容的所有行都放在一行看了,这个是因为xargs的默认分隔符是 回车 **
  • 可以使用 -d 改掉默认分隔符为其他,就不会影响换行了
[root@xiongbinbin test123]# xargs -a c.txt -d '#'
1
2
3
4
5
6
7
8
9
10

2.2 shell 字符

1. 常用的shell字符
! : 执行历史命令  !! 执行上一条命令
$ : 从变量中获取变量的值
+-*\% : 对应数学运算符 加 减 乘 除 取余数
& : 让命令后台执行
; : 分号可以在shell 中一行执行多个命令,命令之间用分号分隔
\ : 转义字符
`` : 反引号,命令中执行命令  echo "today is `date +%F`"
'' : 单引号,脚本中字符要用单引号引起来,但是不同于双引号的是,单引号不解释变量。
"" : 双引号,脚本中出现的字符串可以用双引号引起来

=======================
通配符:
~ : 家目录  
* : 星号是shell中的通配符,匹配所有
? : 问号是shell中的通配符,匹配除回车以外的一个字符
[list] : 匹配[list]中的任意单个字符,本例中是l、i、s、t
[!list] : 匹配除list中的任意单个字符
{string1,string2,...} : 匹配string1,string2或更多字符串

=======================
重定向:
>    覆盖输入
>>   追加输入
<    输出
<<   追加输出

=================
管道命令:
| :  管道符  上一个命令的输出作为下一个命令的输入   cat filename |grep 'abc'

2. 示例
[root@xiongbinbin test123]# touch file{1..10}
[root@xiongbinbin test123]# ll
total 784
-rw-r--r-- 1 root root    993 Nov  7 13:37 1.txt.gz
-rw-r--r-- 1 root root     10 Nov  6 14:11 2.txt
-rw-r--r-- 1 root root      6 Nov  7 15:42 a.txt
-rw-r--r-- 1 root root     20 Nov  7 15:47 b.txt
-rw-r--r-- 1 root root     21 Nov  7 16:33 c.txt
-rw-r--r-- 1 root root      0 Nov  7 17:48 file1
-rw-r--r-- 1 root root      0 Nov  7 17:48 file10
-rw-r--r-- 1 root root      0 Nov  7 17:48 file2
-rw-r--r-- 1 root root      0 Nov  7 17:48 file3
-rw-r--r-- 1 root root      0 Nov  7 17:48 file4
-rw-r--r-- 1 root root      0 Nov  7 17:48 file5
-rw-r--r-- 1 root root      0 Nov  7 17:48 file6
-rw-r--r-- 1 root root      0 Nov  7 17:48 file7
-rw-r--r-- 1 root root      0 Nov  7 17:48 file8
-rw-r--r-- 1 root root      0 Nov  7 17:48 file9
-rw-r--r-- 1 root root 779692 Nov  5 21:51 wget-log

[root@xiongbinbin test123]# rm file[1-5]
rm: remove regular empty file ‘file1’? y
rm: remove regular empty file ‘file2’? y
rm: remove regular empty file ‘file3’? y
rm: remove regular empty file ‘file4’? y
rm: remove regular empty file ‘file5’? y

[root@xiongbinbin test123]# rm file?
rm: remove regular empty file ‘file6’? y
rm: remove regular empty file ‘file7’? y
rm: remove regular empty file ‘file8’? y
rm: remove regular empty file ‘file9’? y

[root@xiongbinbin test123]# rm file[!5-8]
rm: remove regular empty file ‘file1’? y
rm: remove regular empty file ‘file2’? y
rm: remove regular empty file ‘file3’? y
rm: remove regular empty file ‘file4’? y
rm: remove regular empty file ‘file9’? y

2.3 组合命令实战

1. 检索本机的IP、NETMASK、MAC地址、广播地址
[root@ifconfig ens33 |grep -w 'inet' |tr -d [A-Za-z]|tr -s ' '|cut -d ' ' -f2|xargs echo 'IP: '
IP:  192.168.204.3
[root@xiongbinbin test123]# ifconfig ens33 |grep -w 'inet' |tr -d [A-Za-z]|tr -s ' '|cut -d ' ' -f3|xargs echo 'NetMask: '
NetMask:  255.255.255.0
[root@xiongbinbin test123]# ifconfig ens33 |grep -w 'inet' |tr -d [A-Za-z]|tr -s ' '|cut -d ' ' -f4|xargs echo 'Braodcast: '
Braodcast:  192.168.204.255
[root@xiongbinbin test123]# ifconfig ens33 |grep -w 'ether' |tr -d [A-Za-z]|tr -s ' '|cut -d ' ' -f2|xargs echo 'MAC Address: '
MAC Address:  00:0:29:33:8:18

2. 将系统中所有普通用户的用户名、密码和默认shell保存到一个文件中,要求用户名和密码和默认shell之间用tab键分隔
[root@xiongbinbin test123]# grep -i "bash" /etc/passwd |grep -v "root"|cut -d ':' -f 1,2,7|tr ':' '\t'
test123 x       /bin/bash
tomcat  x       /bin/bash
[root@xiongbinbin test123]#

三、shell脚本

3.1、shell脚本介绍
  • 简单来说,就是将需要完成某个任务所执行的命令按照执行顺序保存到文本中,并给予执行权限
  • 示例
创建一个用户:harry  
密码设置为:yunwei.789879
该用户创建文件夹/tmp/tyschool
该用户创建文件/tmp/tyschool/README
将"hello world!"输入到文件/tmp/tyschool/README中
  • 代码实现
useradd harry

echo 'yunwei.789879' |passwd --stdin harry

su - harry -c "mkdir -p /tmp/tyschool"

su - harry -c "touch /tmp/tyschool/README"

su - harry -c "echo 'hello world!' >> /tmp/tyschool/README"

  • su -c 参数的使用
  • su - username -c command
  • -c command 或 --command=command 变更为帐号为 USER 的使用者并执行指令(command)后再变回原来使用者
3.2、shell脚本语法
1. shell脚本的组成
  • 脚本使用帮助说明
  • 脚本执行的前提环境检查和依赖处理
  • 任务执行的代码
  • 完成后的配置
  • 执行过程中产生的垃圾的清除
2. 脚本的命名
  • 要有意义 脚本名称+脚本扩展名
  • 名字不要太长 26个字节以内
3. 代码规范
  • #!/bin/bash 指定脚本执行的解释器
  • # 代表注释,#! 除外
  • 脚本基本信息的描述
//以下内容是对脚本的基本信息描述,可以根据实际情况尽可能写的详细写,方便后续使用
# Name: 脚本名字
# Desc: 描述,describe
# path: 存放路径
# Usage: 用法
# Updata: 更新时间
# Author: 作者
# Release: 发布版本

//下面就是脚本的具体内容
....
4. 脚本执行方法
  • 标准脚本执行方法(建议)

    • 绝对路径执行
    /home/test123/creat_user.sh
    
    • 相对路径执行
    ./creat_user.sh
    
  • 非标准的执行方法(不建议)

bash  creat_user.sh
sh  creat_user.sh
bash -x  creat_user.sh
sh -x  creat_user.sh

-x : 一般在测试中用于排错,查看脚本的执行过程
-n : 用来查看脚本的语法是否有问题
  • 注意: 如果脚本没有加可执行权限,不能使用标准的执行方法执行

  • 命令式脚本执行方法

    • 定义命令路径变量(脚本必须给执行权限)
    PATH=$PATH:脚本路径
    

四、变量

  • 计算机程序在运行的过程中需要将一些数据存放在内存中,需要的时候读出来,计算机内存在计算机中扮演桥梁的作用;
      1. 将数据从硬盘中读出存入内存,从内存读出给CPU
      1. CPU将数据存入内存,内存将数据存入硬盘
4.1、变量的介绍
  • 计算机的存储单位
1TB=1024GB(2^10)
1GB=1024MB(2^10)
1MB=1024KB(2^10)
1KB=1024B (2^10)
1B=8b 	  (2^3)
  • 变量是编程中最常用的一种临时在内存中存取数据的一种方式。

  • 变量的存取原理

关于内存的说明
1、系统启动    内存被按照1B一个单位划分成N块   并且以十六进制为每一个空间编号
2、内存跟踪表记录   使用和未使用的内存的地址编号
3、内存申请   系统从未使用的内存中拿出一个或者一段连续空间  给你使用  同时在内存跟踪表中记录该地址被占用  不再分给别人  同时在系统中建立映射机制比如:变量名 STRING1='ABC' 
name<=>0x5

4、释放内存
从内存跟踪表中将记录删除,下次存数据直接覆盖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h41Rjbp5-1675659763809)(Linux-shell零基础入门到大师.assets/image-20221108100846206.png)]

CHAR1(0x3)=A
从图片可以看出,当我们在脚本中定义变量存值的时候,可以从以下方面看到变化:
1)内存占用:如果存的是一个字符则占用1个字节,如果存的是字符串则是字符串的长度加1个字节长度(\0是一个特殊字符,代表字符串结束)。
2)变量名与内存空间关系:计算机中会将对应的内存空间地址和变量名称绑定在一起,此时代表这段内存空间已经被程序占用,其他程序不可复用;然后将变量名对应的值存在对应内存地址的空间里。
  • 总结:变量是一个存储数据的容器
4.2、变量定义
1.什么时候需要定义变量?
  • 如果某个内容需要多次使用,并且在代码中重复出现,name可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。
  • 在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。
2. 定义一个变量
  • 语法:变量名=值
  • 在shell编程中的变量名和等号之间不能有空格
变量名命名规则:
	命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
	中间不能有空格,可以使用下划线(_)。
	不能使用标点符号。
	不能使用bash里的关键字(可用help命令查看保留关键字)
VAR1=1
age=18  整型
name='zhangsan' 字符串
score=88.8  浮点
  • 注意:字符串要用单引号或者双引号引起来,建议变量名为大写或下划线开头,和命令区分

  • 示例:

变量赋值,此种方法设置为本地变量
[root@xiongbinbin ~]# name='zhangsan'
[root@xiongbinbin ~]# school='jialidun'
[root@xiongbinbin ~]# age='18'
[root@xiongbinbin ~]# score=100
[root@xiongbinbin ~]# echo $age
18
[root@xiongbinbin ~]# echo $name
zhangsan
3. 取消变量 unset
取消当前环境中的变量,如果是变量设置是保存在文件中,下次重启又会恢复
[root@xiongbinbin ~]# unset name
[root@xiongbinbin ~]# echo $name

[root@xiongbinbin ~]#

4. 有类型变量 declare
-i : 将变量看成整数
-r : 使变量只读 readonly, 该变量的值无法改变,并且不能为unset
-x : 标记变量通过环境导出 export
-a : 指定为索引数组(普通数组);查看普通数组
-A : 指定为关联数组;查看关联数组
[root@xiongbinbin ~]# declare -i num='asa'
[root@xiongbinbin ~]# echo $num
0
[root@xiongbinbin ~]# num=100
[root@xiongbinbin ~]# echo $num
100
[root@xiongbinbin ~]# declare -r num
[root@xiongbinbin ~]# echo $num
100
[root@xiongbinbin ~]# num=200
-bash: num: readonly variable
[root@xiongbinbin ~]# unset num
-bash: unset: num: cannot unset: readonly variable
[root@xiongbinbin ~]#
4.3、变量分类
  • 系统中的变量根据作用域及生命周期可以分为四类:本地变量、环境变量、全局变量、内置变量
1. 本地变量
  • 用户自定义的变量,定义在脚本或者当前终端中,脚本执行完毕或终端结束变量失效
2. 环境变量
  • 定义在用户家目录下的**.bashrc.bash_profile**文件中,用户私有变量,只能本用户使用。
    • 查看当前用户的环境变量 env
    • 查询当前用户的多有变量(临时变量和环境变量) set
  • 将当前变量变成环境变量 export
定义一个临时变量
[root@xiongbinbin ~]# export A='hello'  //临时将一个本地变量(临时变量)变成环境变量
[root@xiongbinbin ~]# env|grep ^A
A=hello

定义一个永久生效变量:
vim ~/.bashrc 或者 .bash_profile
A='hello'

关于export说明
用户登录时:
1)用户登录到Linux系统后,系统将启动一个用户shell.在这个shell中,可以使用shell命令或声明变量,也可以创建并运行shell脚本程序。

运行脚本时:
2)运行shell脚本程序时,系统将创建一个子shell。此时,系统中将有两个shell,一个是登录时系统启动的shell,另一个是系统为运行脚本程序创建的shell.当一个脚本程序运行完毕,他的脚本shell将终止,可以返回到执行该脚本之前的shell.

从这种意义上来说,用户可以有许多shell,每个shell都是有某个shell(称之为父shell)派生的。
在子shell中定义的变量只	在该子shell内生效。如果在一个shell脚本程序中定义了一个变量,当该脚本程序运行时,这个定义的变量只是该脚本程序内的一个局部变量,其他的shell不能引用他,要使某个变量的值可以在其他shell中被改变,可以使用export命令对已经定义的变量进行输出。

export命令将使系统在创建每一个新的shell时定义这个变量的一个拷贝。这个过程称之为变量输出。

  • 总结:
    • 本地变量
变量特点:
	作用域 : 只作用于当前shell或脚本
	生命周期 :shell或脚本结束
应用场景 : 临时变量
  • 环境变量
变量特点:
	作用域 : 父shell及子shell
	生命周期 :注销用户或者关机
应用场景 : 用户私有变量

永久定义: ~/.bashrc    ~/.bash_profile
  • 本地变量转换为环境变量
export

用户父shell和子shell的应用和关系
3. 全局变量
  • 使用export 命令将本地变量输出为当前shell中的环境变量
  • 所有用户及shell都可以使用,可以在**/etc/profile** 或者 /etc/bashrc 下永久定义,然后source /etc/profile或/etc/bashrc使立即生效
打印全局变量 printenv

定义格式
export SCHOOL='tyschool'

测试方法:
通过不同用户登陆测试是否能读取变量
4. 内置变量
  • 系统变量(内置bash中变量): shell本身已经固定好了它的名字和作用。
$? : 上一条命令执行后返回的状态;0 :表示执行正常, 非0 表示执行异常或出错;
	若退出状态值为0 : 表示命令运行成功
	若退出状态值为127 : 表示command not found
	若退出状态值为126 : 表示找到了该命令但无法执行(权限不够)
	若退出状态值为1&2 : 表示没有那个文件或目录

$$ : 当前所在进程的进程号  
	echo $$ eg : kill -9 `echo $$`  等价于 exit  # 退出当前会话
	
$! : 后台运行的最后一个进程号  (当前终端) # gedit &
!$ : 调用最后一条命令历史中的参数
!! : 调用最后一条命令历史

$# : 脚本后面接的参数的个数
$* : 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
$@ : 脚本后面所有参数,参数之间是独立的,也是全部输出

$0 : 当前执行的进程/程序名  eg: echo $0
$1~$9 : 位置参数变量
${10}~${n} : 扩展位置参数变量  第10个位置变量必须用{}大括号括起来
  • 总结

    • 全局变量

    • 变量特点:
      	作用域 : 所有用户
      	生命周期 :关机
      应用场景 : 公共变量
      
      永久定义: /etc/profile    /etc/bashrc
      
    • 内置变量

    • 变量特点:
      	作用域 : 所有用户
      	生命周期 :关机
      应用场景 : 公共变量
      
      
4.4、其他常用变量(扩展)
1) 取出一个目录下的目录和文件:dirname 和 basename
2) 变量内容的删除和替换
# : 删除左边第一个
## : 删除左边最后一个
% : 删除右边最后一个
%% : 删除右边第一个

=========================
[root@xiongbinbin ~]# A='/root/Desktop/shell/aa.txt'
[root@xiongbinbin ~]# dirname $A
/root/Desktop/shell
[root@xiongbinbin ~]# basename $A
aa.txt

# url='www.baidu.com'
echo ${#url}   	获取变量的长度
echo ${url#*.}  	以分隔符.为界限  *匹配所有
echo ${url##*.}
echo ${url%.*} 	
echo ${url%%.*} 
============
[root@xiongbinbin ~]# url='www.baidu.com'
[root@xiongbinbin ~]# echo ${#url}
13
[root@xiongbinbin ~]# echo ${url#*.}
baidu.com
[root@xiongbinbin ~]# echo ${url##*.}
com
[root@xiongbinbin ~]# echo ${url%.*}
www.baidu
[root@xiongbinbin ~]# echo ${url%%.*}
www

五、jobs

给虚拟机添加一块磁盘(以sdb为例),要求使用脚本对该磁盘分三个区:
	1)主分区/dev/sdb3  543MB 文件系统ext4 要求开机自动挂载到/data/data1目录
	2)逻辑分区/dev/sdb5 2GB
	3)逻辑分区/dev/sdb6 3GB
	
使用/dev/sdb5 /dev/sdb6 新建卷组vg100,并创建一个PE为16M,容量为2.5GB的逻辑卷lv100,格式化xfs,默认开机自动挂载到/data/data2目录

相关知识点
	fdisk
	mkfs
	/etc/fstab
	lvm
  • 代码实现
#!/bin/bash
# 分区
fdisk /dev/sdb <<EOF
n
p
3

+543
n
e
4


n

+2G
n

+3G
w
EOF

# 2、创建逻辑卷
# 2.1 创建物理卷
pvcreate /dev/sdb5 /dev/sdb6
# 2.2 创建卷组
vgcreate -s 16M vg100 /dev/sdb{5..6}
# 2.3 创建逻辑卷
lvcreate -L 2.5g -n lv100 vg100

# 3、格式化
mkfs.ext4 /dev/sdb3
mkfs.xfs /dev/vg100/lv100

# 4、修改/etc/fstab,实现自动挂载
echo -e "/dev/sdb3\t/data/data1\text4\tdefaults\t0 0" >>/etc/fstab
echo -e "/dev/vg100/lv100\t/data/data2\txfs\tdefaults\t0 0" >>/etc/fstab

# 5、挂载分区
mkdir -p /data/data{1..2}
mount -a

# 6、验证并输出挂载结果
mount |grep "/dev/sdb3"
test $? -eq 0 && echo "/dev/sdb3 挂载成功"|| echo "/dev/sdb3 挂载失败"
##注意检索的时候,mount输出中LV的表示方式,或者直接检索挂载点/data/data2也可以。
mount |grep "vg100-lv100
test $? -eq 0 && echo "/dev/vg100/lv100 挂载成功" || echo "/dev/vg100/lv100 挂载失败"

Shell 进阶

一、shell格式化输出

1.1、echo 命令
  • 功能:将内容输出到默认显示 设备,可以使用重定向将内容输出到指定文件
  • 应用场景:需要计算机程序输出 的地方
语法:echo [-ne] [字符串]
补充说明:echo 会将输入的字符串送往标准输出。输出的字符串可以是空白字符隔开,并在最后加上换行符;

OPTIONS:
-n : 不要在最后自动换行,一般用于结合交互输入
-e : 解释转义字符;即若字符串中出现以下字符,则特别加以处理,而不会将它们当成一般文字输出;

    转义字符:
    \a : 发出警告声
    \b : 删除前一个字符
    \t : 插入tab
    \n : 换行,且光标移至行首

    \c : 最后不加上换行符号
    \f : 换行但光标仍旧停留在原来的位置
    \r : 光标移至行首,但不换行
    \v : 与 \f 相同
    \  : 插入 \ 字符
    \0nnn : 打印nnn(八进制)所代表的ASCII字符;备注:数字0,不要当成字母o
    \xNN : 打印NN(十六进制)所代表的ASCII字符

--help : 显示帮助
--version : 显示版本信息
[root@xiongbinbin ~]# echo "hello world"
hello world
[root@xiongbinbin ~]# echo -n "hello world"
hello world[root@xiongbinbin ~]#
[root@xiongbinbin ~]# echo -e "\t\thello world\n\n"
                hello world


[root@xiongbinbin ~]#

1.2、输出字体颜色
  • echo 默认输出的内容不带颜色,若想要显示颜色,需要使用 参数 -e
语法:(五部分组成)
echo -e "\033[字背景颜色;文字颜色m字符串\033[0m"
	1. \033[...\033[     # 固定写法
	2. 字背景颜色		# [40-47]
	3. ;				# 英文分号
	4. 文字颜色m		 # [30-37]
	5. 0m				# 特效 常用有[0/1/4/5/7/8]
	
eg:echo -e "\033[41;36m something here \033[0m"
其中41的位置代表底色,36的位置是代表字的颜色
1、字背景颜色和文字颜色之间是英文的分号(;)中间不能有空格;
2、文字颜色后面有个m
3、字符串前后可以没有空格。如果有的话,输出也是同样有空格;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzNZjoHn-1675659763809)(Linux-shell零基础入门到大师.assets/image-20221108151239335.png)]

字颜色: 30-37
字背景颜色:40-47
最后面控制选项说明:
  \33[0m 关闭所有属性 
  \33[1m 设置高亮度 
  \33[4m 下划线 
  \33[5m 闪烁 
  \33[7m 反显 
  \33[8m 消隐 
  \33[30m — \33[37m 设置前景色 
  \33[40m — \33[47m 设置背景色 
  \33[nA 光标上移n行 
  \33[nB 光标下移n行 
  \33[nC 光标右移n行 
  \33[nD 光标左移n行 
  \33[y;xH设置光标位置 
  \33[2J 清屏 
  \33[K 清除从光标到行尾的内容 
  \33[s 保存光标位置 
  \33[u 恢复光标位置 
  \33[?25l 隐藏光标 
  \33[?25h 显示光标

字颜色: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;37m 红底白字 \033[0m" 
  echo -e "\033[42;37m 绿底白字 \033[0m" 
  echo -e "\033[43;37m 黄底白字 \033[0m" 
  echo -e "\033[44;37m 蓝底白字 \033[0m" 
  echo -e "\033[45;37m 紫底白字 \033[0m" 
  echo -e "\033[46;37m 天蓝底白字 \033[0m" 
  echo -e "\033[47;30m 白底黑字 \033[0m"

二、shell脚本交互

2.1、read命令
  • 功能:默认接受键盘的输入,回车代表输入结束
  • 应用场景:人机交互
语法:
read [options] var

OPTIONS:
	-p : 打印信息  
	-t : 限定时间  # 限定输入等待时间
	-s : 不回显    # 表示输入的内容隐藏不显示
	-n : 输入字符个数  # 限定输入字符串的个数
var : 使用变量var来接收用户输入
  • 案例:
模拟登录界面

#!/bin/bash

echo "CentOS Linux 8 (Core)"
echo -e "Kernel `uname -r` on an `uname -m`"

echo -n "$HOSTNAME login: "
read myuser

read -p "password: " -s -t 5 -n 2 passwd

echo -e "\n输入的用户名:$myuser  密码:$passwd"
=====执行脚本=====
[test123@xiongbinbin ~]$ sh login_script.sh
CentOS Linux 8 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
xiongbinbin login: root
password:
输入的用户名:root  密码:12

三、shell运算

3.1、赋值运算
赋值运算符
=
语法: 同定义变量语法
重点:字符串必须用引号引起来

a=10
name="张三"
3.2、算数运算(整形和浮点)
  • 整形运算
四则运算符:
+ : 
-
* 
/
扩展:
%  : 取余
** : 幂运算
+= : 加等于
-= : 减等于
*= : 乘等于
/= : 除等于
%= : 取余后赋值给其变量
shell的算数运算中有以下几种方法:
expr  let   $(())  $[]  bc
    expr : 只能做整数运算,表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2;做乘*时要转义 \* 不然会被认为是通配符
    let : 只能做整数运算,变量运算;表达式中的变量前不必有$,如果表达式中包含了空格或其他特殊字符,则必须引起来
    $(()) : 只能做整形运算
    $[]   : 只能做整形运算
 
名称	                  语法	                            范例
算术扩展	            变量=$((算术表达式))	              r=$((1+2*3))
使用外部程序expr	      变量=`expr 算术表达式`	            r=`expr 1 + 2 \* 3`
使用[]	             变量=$[算术表达式] 	                r=$[1+2]
使用内置命令declare	  declare -i 变量=算术表达式	        declare -i r=1+2*3
使用内置命令let	      let 算术表达式	                      let r=1+2
[test123@xiongbinbin ~]$ let a=100+3
[test123@xiongbinbin ~]$ let a=100+3;echo $a
103
[test123@xiongbinbin ~]$ let a=100*3;echo $a
300
[test123@xiongbinbin ~]$ let a=100/3;echo $a
33
[test123@xiongbinbin ~]$ let a=100**3;echo $a
1000000
[test123@xiongbinbin ~]$ let a=100%3;echo $a
1
[test123@xiongbinbin ~]$ let a++;echo $a
2
[test123@xiongbinbin ~]$ let a+=10;echo $a
12
[test123@xiongbinbin ~]$ let a-=10;echo $a
2
[test123@xiongbinbin ~]$ let a-=10;echo $a

  • 浮点运算(bc)
bc是Linux文本界面的计算器,可以计算整形和浮点数的运算。做浮点运算时,要先指定小数点精度

scale=N  小数点的数量

浮点运算中,同优先级的情况下,先乘后除精度更高

echo "scale=2;100/3"|bc

[test123@xiongbinbin ~]$ echo "scale=2;100/3"|bc
33.33
[test123@xiongbinbin ~]$
  • job: 计算内存使用率
job思考
1、获取内存总量  free top  /proc/meminfo
2、内存使用量
3、内存使用率计算公式   使用量/总量*100%

=========================
#!/bin/bash
FREE=`head -2 /proc/meminfo |tr -s " "|cut -d " " -f 2|awk NR==2`
TOTAL=`head -2 /proc/meminfo |tr -s " "|cut -d " " -f 2|awk NR==1`

echo "内存使用率:`echo "scale=2;($TOTAL-$FREE)*100/$TOTAL"|bc`%"

[test123@xiongbinbin ~]$ sh count_meminfo.sh
内存使用率:92.99%
3.3、比较运算
  • 整形比较运算
整形比较运算符解释
精准比较:
	-eq : 等于 equal
	-gt : 大于
	-lt : 小于
模糊比较:
	-ge : 大于或等于
	-le : 小于或等于
	-ne : 不等于
  • 字符串比较运算
字符串比较运算符解释, 注意字符串一定要使用引号引起来
	== : 等于
	!= : 不等于
	-n : 检查字符串的长度是否大于0,大于0为真
	-z : 检查字符串的长度是否为0,等于0为真

====================
[test123@xiongbinbin ~]$ test 'root' == 'root';echo $?
0
[test123@xiongbinbin ~]$ test 'root' != 'root';echo $?
1
[test123@xiongbinbin ~]$ name=
[test123@xiongbinbin ~]$ test -z "$name";echo $?
0
[test123@xiongbinbin ~]$ test -n "$name";echo $?
[test123@xiongbinbin ~]$ test "$name";echo $?
1
[test123@xiongbinbin ~]$

3.4、逻辑运算
  • 完成一个任务需要多个条件判断结果,才能得出结论
逻辑运算符:
	&& : 逻辑与运算,即and
	|| : 逻辑或运算,即or
	!  : 逻辑非运算,即取反
  • 案例
job  用户登录
要求用户输入的用户名和密码同时正确才能登录

思路:
1、输入用户名
2、输入密码
3、与运算返回结果

脚本代码
#!/bin/bash

echo "CentOS Linux 8 (Core)"
echo -e "Kernel `uname -r` on an `uname -m`"

# echo -n "$HOSTNAME login: "
read -p "$HOSTNAME login: " myuser

read -p "password: " -s -t 5 passwd

echo -e "\n输入的用户名:$myuser  密码:$passwd"

test $myuser == 'root' && test $passwd == '123456'
test $? -eq 0 && echo "login success" ||echo "login faild"

======================
[test123@xiongbinbin ~]$ sh  login_test.sh
CentOS Linux 8 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
xiongbinbin login: root
password:
输入的用户名:root  密码:123456
login success

[test123@xiongbinbin ~]$ sh  login_test.sh
CentOS Linux 8 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
xiongbinbin login: toot
password:
输入的用户名:toot  密码:123456
login faild

3.5、文件类型、权限、新旧判断
  • 文件类型的表示
  • 文件权限的判断
  • 文件新旧以及相同文件的相关判断
-d : 检查是否存在且为目录
-e : 检查是否存在
-f : 检查是否存在且文件
-r : 检查是否存在且可读
-s : 检查是否存在且不为空
-w : 检查是否存在且可写
-x : 检查是否存在且可执行
-O : 检查是否存在且被当前用户拥有
-G : 检查是否存在且默认组为当前用户组

file1 -nt file2  检查file1是否比file2新
  • 更多相关选项可以通过 man test 查看
[test123@xiongbinbin ~]$ test -d '/root';echo $?
0
[test123@xiongbinbin ~]$ test -f '/root';echo $?
1
[test123@xiongbinbin ~]$ test -G '/root';echo $?
1
[test123@xiongbinbin ~]$ test -G '/home/test123';echo $?
0

四、数组

4.1、数组介绍
  • 数组可以让用户一次赋予多个值,需要读取数据时只需要通过索引调用就可以方便读出了
  • 普通数组:只能使用整数作为数组索引(元素的索引)
  • 关联数组:可以使用字符串作为数组索引(元素的索引)
4.2、数组定义
数组名称=(元素1 元素2 ....元素N)
  • 一次赋一个值:
变量名=变量值
array[0]=v1
array[1]=v2
array[2]=v3
array[3]=v4
  • 一次赋多个值:
array=(var1 var2 var3 var4)
array1=(`cat /etc/passwd`)  //将文件中每一行赋值给array数组
array2=(`ls /root`)
array3=(harry amy jack "miss zhang")
array4=(1 2 3 4 "hello world" [10]=linux)
4.3、数组取值
${array[i]}  i表示元素的索引;索引是数据在数组中的位置编号,从0开始
使用 @ 或 * 可以获取数组中的所有元素

${array[0]}		获取第一个元素
${array[*]}		获取数组里的所有元素		
${array[@]}		获取数组里的所有元素
${#array[*]}	获取数组的长度即元素的个数
${!array[@]}	获取数组元素的索引
${array[@]:1:2}	访问指定的元素;1代表从索引为1的元素开始获取;2代表获取后面几个元素
#!/bin/bash

array=(`cat /etc/passwd`)
echo ${array[@]}
echo ${#array[@]}
echo ${!array[@]}
echo ${array[@]:1:3}
function a {
j=1
for i in ${array[@]}:
do
echo $j = $i
let j++
done
}
==============
[test123@xiongbinbin ~]$ sh array_test.sh
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin polkitd:x:999:998:User for polkitd:/:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin chrony:x:998:996::/var/lib/chrony:/sbin/nologin test123:x:1000:1000:test123:/home/test123:/bin/bash ntp:x:38:38::/etc/ntp:/sbin/nologin mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false tomcat:x:1001:1001::/home/tomcat:/bin/bash nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/nologin rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin gluster:x:996:992:GlusterFS daemons:/run/gluster:/sbin/nologin libstoragemgmt:x:995:991:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin qemu:x:107:107:qemu user:/:/sbin/nologin unbound:x:994:990:Unbound DNS resolver:/etc/unbound:/sbin/nologin usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin geoclue:x:993:989:User for geoclue:/var/lib/geoclue:/sbin/nologin radvd:x:75:75:radvd user:/:/sbin/nologin rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin saslauth:x:992:76:Saslauthd user:/run/saslauthd:/sbin/nologin pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin saned:x:991:985:SANE scanner daemon user:/usr/share/sane:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin colord:x:990:984:User for colord:/var/lib/colord:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin setroubleshoot:x:989:983::/var/lib/setroubleshoot:/sbin/nologin sssd:x:988:982:User for sssd:/:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin gnome-initial-setup:x:987:981::/run/gnome-initial-setup/:/sbin/nologin avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin harry:x:1002:1002::/home/harry:/bin/bash
96
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin

4.4、关联数组
  • 关联数组和基本数组一样,是一个内存存值的容器
  • 关联数组可以自定义索引,是一个无序数组
首先要声明关联数组: declare -A
declare -A asso_array1
declare -A asso_array2
declare -A asso_array3

数组赋值:
一次赋一个值:
数组名[索引名]=变量值
[test123@xiongbinbin ~]$ declare -A array1
[test123@xiongbinbin ~]$ array1[linux]=one
[test123@xiongbinbin ~]$ array1[java]=two
[test123@xiongbinbin ~]$ array1[python]=three

一次赋多个值:
[test123@xiongbinbin ~]$ declare -A array2
[test123@xiongbinbin ~]$ array2=([name1]=harry [name2]=root [name3]=test123)

查看关联数组:declare -A
[test123@xiongbinbin ~]$ declare -A|grep array
declare -A array1='([java]="two" [linux]="one" [python]="three" )'
declare -A array2='([name3]="test123" [name2]="root" [name1]="harry" )'
[test123@xiongbinbin ~]$

关联数组取值
${数组名称[索引名称]}

获取数组元素的索引
${!array[@]}	

jobs

案例:
分别打印CPU 1min 5min 15min load负载值

job思考:
1)如何获取CPU load 平均负载值,有哪些命令:top uptime
2)如何存储在内存中,变量、数组

job步骤:
1)收集cpu load 平均负载值
2)打印输出对应的负载值

代码实现

五、流程控制

5.1、if判断

  • if 语句在程序中是用来作判断的,用在需要判断的场景中,提供脚本的可执行性
5.1.1、单if判断
语法:
if [ condition ]  #condition 值为True or False ;条件和中括号之间要有空格
	then   		 #条件为真的时候执行
		commands  # 代码块 一行或者多行代码
fi				  # 必须加上结尾符号 fi代表语句结束
#!/bin/bash

if [ $USER != 'root' ]
        then
        echo "ERROR: $USER have not authorited excuted please use root"
        exit 1
fi
5.1.2、if…else
语法:
if [ condition ]
	then
		commands1
else
		commands2
fi
#!bin/bash

if [ $USER == 'root' ]
   then
        echo -e "\033[33mroot can not start \033[0m"
else
        echo -e "\033[33mstart successful \033[0m"
fi

5.1.3、if…elif…else
  • 用于多条件判断
语法:
if [ condition1 ]	#满足第一个条件
	then		   # 真
		command1   # 执行command1
elif [ condition2 ] # 满足第二个条件
	then			# 真
		command2	# 执行command2
...........
else				# 如果条件都不满足
		commandN	# 执行commandN
fi					# 结束判断
监控内存使用率
#!/bin/bash
#declare -i used_rate
#read -p "请输入内存使用率:" used_rate

if [ $1 -gt 80 ]
   then
        echo -e "\033[31m内存使用超出80%,情况非常严重,请及时处理!\033[0m"
elif [ $1 -gt 70 ]
   then
        echo -e "\033[35m超出70%,内存占用较严重!\033[0m"
elif [ $1 -gt 60 ]
    then
        echo -e "\033[33m超出60%,请注意观察!\033[0m"
else
        echo -e "\033[32mok \033[0m"
fi

==================
[test123@xiongbinbin class01]$ sh test_manyif.sh 65
超出60%,请注意观察!
[test123@xiongbinbin class01]$ sh test_manyif.sh 75
超出70%,内存占用较严重!
[test123@xiongbinbin class01]$ sh test_manyif.sh 85
内存使用超出80%,情况非常严重,请及时处理!
[test123@xiongbinbin class01]$ sh test_manyif.sh 50
ok

5.1.4、if嵌套if
  • 当有多步判断的时候,可以使用if嵌套
  • 多步判断,类似于多条件if,依赖顺序执行
语法:
if [ condition1 ]
	then
		if [ condation2 ]
			then
				....
		fi
else
	commandN
fi
#!/bin/bash

if [ $1 -gt 18 ]
   then
        if [ $2 == "会员" ]
           then
                echo "允许进入健身房!"
        else
                echo "需要会员才能进入!"
        fi
else
        echo "不能进入健身房!"
fi

====================
[test123@xiongbinbin class01]$ sh test_ifqiantao.sh 19 会员
允许进入健身房!
[test123@xiongbinbin class01]$ sh test_ifqiantao.sh 19 普通用户
需要会员才能进入!
[test123@xiongbinbin class01]$ sh test_ifqiantao.sh 17 普通用户
不能进入健身房!

#!/bin/bash

if ./config 1>/dev/null ;then
        if make 1>/dev/null ;then
                if make install 1>/dev/null ;then
                        echo "install successful"
                else
                        echo "install faild"
                fi
        else
                echo "make faild"
        fi
else
        echo "config faild"
fi

5.2、if与shell运算

5.2.1、文件是否存在与否的判断
-d : 检查是否存在且为目录
-e : 检查是否存在
-f : 检查是否存在且文件
-s : 检查是否存在且不为空
-p : pipe
-c : character
-b : block
-L : 软链接
!/bin/bash
# 1 判断目录 /temp/tyschool是否存在,没有就创建
if [ ! -d /temp/tyschool ] ;then
       mkdir -v /temp/tyschool
else
       echo "/temp/tyschool already exist"
fi

# 2 判断/temp/tyschool/linux文件,是否拥有执行权限,没有就报错,有就执行它
if [ -x /temp/tyschool/linux ] ;then
        sh /temp/tyschool/linux
else
        echo "ERROR: 没有执行权限"
fi

5.2.2、文件权限相关的额判断
-r : 检查是否存在且可读
-s : 检查是否存在且不为空
-w : 检查是否存在且可写
-x : 检查是否存在且可执行
-O : 检查是否存在且被当前用户拥有
-G : 检查是否存在且默认组为当前用户组
5.2.3、两个文件的比较判断
file1 -nt file2  比较file1是否比file2新
file1 -ot file2  比较file1是否比file2旧
file1 -ef file2  比较是否为同一个文件,或者用于判断硬链接,是否指向同一个inode
5.2.4、整数之间的判断
精准比较:
	-eq : 等于 equal
	-gt : 大于
	-lt : 小于
模糊比较:
	-ge : 大于或等于
	-le : 小于或等于
	-ne : 不等于
	
浮点比较运算
	思路:
	1、先处理为整形(扩大X倍)
	2、比较
5.2.5、字符串之间的判断
== : 等于
!= : 不等于
-n : 判断是否非空
-z : 判断是否为空
5.2.6、多重条件判断
逻辑判断符号:
-a  和 &&   (and 逻辑与)
-o  和 ||   (or 逻辑或)
!  非运算

语法:
if [ condition1 ] && [ condition2 ]
if [ condition1 ] -a [ condition2 ]
if [ condition1 ] || [ condition2 ]
if [ condition1 ] -o [ condition2 ]

5.3、if 高级用法

5.3.1、if (())
  • 条件符号使用双圆括号,可以在条件中植入数学表达式
if (( (5+5-5)*5/5 > 10 )) ;then
	echo "yes"
else
	echo "no"
5.3.2、if [[]]
  • 使用双方括号,可以在条件中使用通配符
for var in ab ac rx bx rvv vt
do
	if [[ "$var" == r* ]] ;then
		echo "$var"
	fi
done

5.4、简写 if

  • 省去了关键字,条件为真采用 && 符号链接命令块,条件为假采用 || 链接命令块
  • 简写 if 一般用在简单的判断中
示例:
if [ ! -d /temp/tyschool ] ;then
	mkdir /temp/tyschool
fi

可以简写为
[ !  -d /temp/tyschool ] && mkdir /temp/tyschool

if [ $USER == 'root' ] ;then
	echo "hello root"
else
	echo "hello guest"
fi

可以简写为
[ $USER == 'root' ] && echo "hello root" || echo "hello guest"


5.5、循环语句

5.5.1、循环语句-for
1、for介绍
  • 脚本在执行任务的时候,总会遇到需要循环执行的时候
  • 节省内存
  • 节省开发时间成本
2、for基本语法
  • shell风格,类似python
一、带迭代对象
for   var  in  可迭代的对象
do
	循环体
done

二、不带迭代对象,执行时由用户指定参数和参数的个数
for variable
do
	循环体
done
for var in {1..5}
do
	echo $var
done

for var in {1..5..2}
do
	echo $var
done

for var in `seq 5`
do
	echo $var
done

for var in `seq 1 +2 5`
do
	echo $var
done

==============
#!/bin/bash

for var
do
        echo $var
done

[test123@xiongbinbin class02]$ sh for_2.sh 1 2 3
1
2
3

  • java风格
for( i=1;i<100;i++ )
{
    循环体
}
for( i=1;i<=5;i++ )
{
    echo $i
}
  • C语言风格 用于一个for循环中可以有多个条件
for(( expr1;expr2;expr3 ))  #2个括号
do         #没有花括号,用do和done来包裹循环体
    循环体
done

for(( i=1;i<=5;i++ ))  #2个括号
do         #没有花括号,用do和done来包裹循环体
    echo $i
done

expr1 : 定义变量并赋初始值 
expr2 : 决定是否循环(条件)
expr3 : 决定循环变量如何改变,决定循环什么时候退出  自增或自减运算

多变量用法:
for (( A=1,B=10;A<10,B>1;A++,B-- ))
for(( i=1;i<=5;i++ )) ;do echo $i ;done
  • for 循环的多线程后台执行
for conditions
do
(
	循环体
) &
done

( ) &  将循环体作为一个组放到后台并发执行,可以节省代码运行时间
#!/bin/bash

netsub="192.168.204."

for ip in `seq 10`
do
(
        if ping -c1 $netsub$ip >/dev/null 2>&1 ;then
                echo $netsub$ip is open
        else
                echo $netsub$ip is close
        fi
) &
done

3、for循环应用
  • jobs: 写一个扫描软件,扫描本地网络中存活的机器
#!/bin/bash

netsub="192.168.204."

for ip in `seq 10`
do
        if ping -c1 $netsub$ip >/dev/null 2>&1 ;then
                echo $netsub$ip is open
        else
                echo $netsub$ip is close
        fi
done

4、循环控制-break
  • 打断本次循环,执行循环体外面的代码
#!/bin/bash
for i in `seq 10`
do
        if [ $i -eq 5 ] ;then
                break
        else
                echo $i
        fi
done
echo "执行完毕"


[root@xiongbinbin class02]# sh break_1.sh
1
2
3
4
执行完毕

5、循环控制-continue
  • 跳过某次循环,继续下一次循环;表示循环体内下面的的代码不执行,重新开始下一次循环
#!/bin/bash

for i in `seq 10`
do
        if [ $i -eq 5 ] ;then
                continue
        else
                echo $i
        fi
done
echo "执行完毕"


[root@xiongbinbin class02]# sh continue_1.sh
1
2
3
4
6
7
8
9
10
执行完毕
6、循环控制-sleep
  • 控制循环的节奏;控制循环的频率
#!/bin/bash

# 倒计时
for i in `seq 10 -1 0`
do
        echo -e -n "\b$i"
        sleep 1
done
echo -e "\n执行完毕"

7、参数控制命令-shift
  • 使位置参数向左移动,默认移动一位,可以使用shift N 传参要是N的整数倍
  • 使用场景:外部传参到循环内部,解决参数移动的问题
#!/bin/bash

# 1、判断外部传参的数量
[ $# -lt 3 ] && echo '请输入至少三位参数:"$0" $1 $2 $3 ...' && exit 1

# 将参数的数量赋值给count
count=$#

# 通过shift左移,将参数输出
for (( i=1;i<=$count;i++ ))
do
        echo "参数数量:$#"
        echo '当前$1的数值是:'$1''
        shift 1
        sleep 1
done
echo "执行完毕"

[root@xiongbinbin class02]# sh shift_1.sh a b c d e f
参数数量:6
当前$1的数值是:a
参数数量:5
当前$1的数值是:b
参数数量:4
当前$1的数值是:c
参数数量:3
当前$1的数值是:d
参数数量:2
当前$1的数值是:e
参数数量:1
当前$1的数值是:f
执行完毕

8、脚本退出命令exit
  • 脚本退出的结束语句,退出代码,exit后可以设置程序执行结果
  • 退出,直接退出程序,释放所有执行该脚本时申请的资源
  • 成功,返回0
  • 不成功,返回非零值。通常都被解释,翻译成一个错误码
Bash命令,脚本和脚本中的函数都会返回退出状态码;
这些是脚本中本身有的含义在写脚本中不要使用一下数字

退出码               含义
--------------------------------
1				通用错误
2				Shell内建命令使用错误(Bash文档上有说明)
126				命令调用不能执行
128				"command not found"
128+n			Exit的参数错误
130				用Ctrl -C 来结束脚本
255*-			超出范围的退出状态
#!/bin/bash

for i in `seq 10`
do
        echo $i
        if [ $i -eq 5 ] ;then
                exit 0
        fi
done
echo "执行完毕"


[root@xiongbinbin class02]# sh exit_1.sh
1
2
3
4
5
[root@xiongbinbin class02]# echo $?
0

9、for嵌套
  • for 与 if 嵌套
#!/bin/bash

for (( num=1;num<=10;num++ ))
do
        echo $num
        if [ $num -eq 5 ] ;then
                break
        fi
done
echo "执行完毕"

[root@xiongbinbin class02]# sh for_if.sh
1
2
3
4
5
执行完毕

  • for 与 for 嵌套
 #!/bin/bash

for (( A=1;A<=9;A++ ))
do
        for (( B=1;B<=A;B++ ))
        do
                echo -n -e "$A*$B =$((A*B))\t"
        done
        echo
done

10、for实战
  • 数组读出、读入
    • 如何获取数组中元素的数量:${#array[*]}
    • 数组存值,如果需要遍历的话,那么主要索引的定义:数组的索引从0开始,长度减1结束
    • 数组的读出:${array[index]}
5.5.2、循环语句-while
1、while介绍
  • 条件为真就进入循环;条件为假就退出循环;一般用在未知循环次数的环境
2、while语法
while [condition]   # 条件为真进入循环,条件为假,退出循环
	do
		command
	done
	
while [ 1 -eq 1]
	do
		command
		command
		....
	done
	
===============================
打印1-5数字
1、使用while循环
#!/bin/bash

i=1
while [ $i -le 5 ]
do
    echo $i
    let i+=1
done

2、使用for循环
#!/bin/bash

for(( i=1;i<=5;i++ ))
do
    echo $i
done
3、while与shell运算
  • 比较运算
示例1:按Q退出程序

#!/bin/bash

read -p "请输入一个字符[按Q退出]:" choose

while [ $choose != "Q" ]
do
        echo "你输入的字符是:$choose"
        read -p "请输入一个字符[按Q退出]:" choose
done

示例2:打印数字1-5

#!/bin/bash

num=1
while [ $num -le 5 ]
do
        echo $num
        num=$((num+1))
done

  • 逻辑运算
#!/bin/bash

read -p "你有多少钱?:" money
read -p "你有几辆车?:" car
read -p "你有几套房?:" hourse

while [ $money -lt 100000 ] || [ $car -lt 2 ] || [ $hourse -lt 2 ]
do
        echo "有请下一位!"
        read -p "你有多少钱?:" money
        read -p "你有几辆车?:" car
        read -p "你有几套房?:" hourse
done
echo "乖女婿,你怎么才来啊!女儿许给你了!"

  • 特殊条件(True/False/冒号 “:” 适用于死循环)
1、特殊符号  冒号 : 代表真

2、布尔值: True     代表真
		   False    代表假


#!/bin/bash

while :
do
	echo hahaha
	sleep 1
done

#!/bin/bash

while True
do
	echo hahaha
	sleep 1
done

4、while与循环控制语句
  • break
#!/bin/bash

num=1
while [ $num -le 10 ]
do
        echo $num
        if [ $num -eq 5 ] ;then
        break
        fi
        num=$((num+1))
        
done
  • continue
#!/bin/bash

num=0
while [ $num -lt 10 ]
do
        let num++
        if [ $num -eq 5  ];then
                continue
        fi
        echo $num
done

# 这里比较绕,continue是跳出本次循环,所以循环体要在continue后面
  • sleep
#!/bin/bash

while True
do
	echo hahaha
	sleep 1
done
5、while嵌套其他语句
  • while与if嵌套
#!/bin/bash

num=1
while [ $num -le 10 ]
do
        echo $num
        if [ $num -eq 5 ] ;then
        break
        fi
        num=$((num+1))
        
done
  • while与for嵌套
#!/bin/bash

A=1
while [ $A -le 9 ]
do
        for (( B=1;B<=$A;B++ ))
        do
                echo -n -e "$A*$B =$((A*B))\t"
        done
        let A++
        echo
done

  • while与while嵌套
#!/bin/bash

A=1
while [ $A -le 9 ]
do
        B=1
        while [ $B -le $A ]
        do
                echo -n -e "$A*$B =$((A*B))\t"
                let B++
        done
        let A++
        echo
done

5.5.3、循环语句-until
1、until介绍
  • 和while的循环条件相反,条件为假就进入循环,条件为真就退出循环

  • 特点:条件为假就进入循环,条件为真就退出循环

2、until语法
until [condition]
	do
		command
		.....
	done
  • 示例:
#!/bin/bash

num=1
until [ $num -gt 5 ]
do
        echo $num
        num=$((num+1))
done

====================
对此while循环
#!/bin/bash

num=1
while [ $num -le 5 ]
do
        echo $num
        num=$((num+1))
done

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EgMJyunS-1675659763810)(Linux-shell零基础入门到大师.assets/image-20221110172850906.png)]

六、函数与case

6.1、函数
1、函数的介绍
  • shell中将一组命令的集合或语句形成一段可用的代码,这些代码块称为shell函数。给这段代码起个名字称为函数名,后续可以直接调用该段代码的功能。

  • 简而言之,就是将完成一个功能的一段代码进行命名、封装

  • 函数的优点:

    • 代码模块化,调用方便,节省内存
    • 代码模块化,代码量少,拍错简单
    • 代码模块化,可以改变代码的执行顺序
2、函数的定义
  • 函数的语法
语法一:

函数名 () {
	代码块
	return N
}

语法二:
function 函数名 {
	代码块
	return N
}

函数中的return说明:
1.return 可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码)
2.return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。
3.如果没有return命令,函数将返回最后一个shell的退出值。
fun1 () {
	echo "first function"
	echo "hahaha"
	return 0
}

function fun2 {
	echo "sec function"
	echo "hehe"
	return 0
}
3、函数的调用
  • 函数名调用(注意函数名后面不要加小括号)
fun1 () {
	echo "first function"
	echo "hahaha"
	return 0
}

function fun2 {
	echo "sec function"
	echo "hehe"
	return 0
}

fun1
fun2
  • 当前命令行调用
在一个文件中定义好要调用的函数,然后通过 (source 文件名 或者 . 文件名)   将函数加载带内存中;就可以直接在当前命令行输入函数名进行调用了

[root@xiongbinbin class04]# cat fun1.sh
################################
# Author:                      #
# Create_Date:   2022-11-10    #
# Version:                     #
# Descripition:                #
################################
#!/bin/bash
hello () {
        echo "hello $USER"
        echo "hello $1"
}

function menu {
        cat <<-EOF
1.mysql
2.web
3.app
4.exit
EOF
}

[root@xiongbinbin class04]# source fun1.sh
[root@xiongbinbin class04]# . fun1.sh

[root@xiongbinbin class04]# hello admin
hello root
hello admin
[root@xiongbinbin class04]# menu
1.mysql
2.web
3.app
4.exit
[root@xiongbinbin class04]#

  • 定义到用户的环境变量中
/etc/profile   /etc/bashrc  ~/.bashrc  ~/.bash_profile


[root@xiongbinbin ~]# cat .bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

hello () {
        echo "hello $USER"
        echo "hello $1"
}

function menu {
        cat <<-EOF
1.mysql
2.web
3.app
4.exit
EOF
}

当用户打开bash的时候就会读取该文件
  • 脚本中调用
#!/bin/bash
# 打印菜单
source ./fun1.sh  //这里调用的是上面那个文件,这样做的目的是将多个文件中的函数合在一个文件中
function menu {
        cat <<-EOF
h 显示帮助信息
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
EOF
}

menu  // 调用函数
6.2、Case语句
1、Case的介绍
  • 条件分支语句,根据用户给予的条件去和自己预设的条件匹配,匹配成功则执行对应条件下的代码

  • 特点:根据给与的不同条件执行不同的代码块

2、Case的语法及应用
语法:
case $var in		# 定义变量; var 代表是变量名
pattern1)			# 模式X; 用 | 分割多个模式,相当于or
	command1		# 需要执行的语句
	;;				# 两个分号代表命令结束
pattern2)
	command2
	;;
pattern3)
	command3
	;;
	*)				# deault, 不满足以上模式,默认执行*)下面的语句
	command4
	;;
esac				# esac表示case语句结束
#!/bin/bash

read -p "性别:" gender

case $gender in
        B|b|)
                echo "先生,您好!"
                ;;
        G|g|)
                echo "女士,您好!"
                ;;
        *)
                echo "请输入性别!"
esac

七、正则表达式

7.1、正则表达式的介绍
1、正则表达式定义
  • 正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。
  • 支持正则表达式的程序如:locata | find | vim | grep | sed | awk
7.2、正则表达式的特殊字符
1、位置限定符
  • 定位符使用技巧:同时锚定开头和结尾,做精确匹配;单一锚定开头或结尾或者不锚定的,做模糊匹配
元字符说明举例
^匹配行首的位置,以什么开头;a.位于[ ]括号内,则匹配除括号中字符之外的任意字符,也就是对[ ]括号内的字符取反;b.位于[ ]括号外面,则表示以[ ]中的任意一个字符开头^a:表示匹配文件中以a开头的行;[ ^0-9]:表示匹配任意一位非数字字符;
$匹配行尾的位置,以什么结尾“a$”:表示匹配以a结尾的行;
  • 示例:
1) 精确匹配 以a开头,c结尾的字符串

[root@xiongbinbin class04]# egrep "^ac$" a.txt
ac

2) 模糊匹配 以a开头

[root@xiongbinbin class04]# egrep "^a" a.txt
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin

3) 模糊匹配 以c结尾的字符串

[root@xiongbinbin class04]# egrep "c$" a.txt
sync:x:5:0:sync:/sbin:/bin/sync
ac

4) 模糊匹配 以a开头,以c结尾,中间任意字符的字符串

[root@xiongbinbin class04]# egrep "^a.*c$" a.txt
ac
ahfdjhdjghjdghc

2、匹配符
匹配符说明举例
.匹配除回车以外的任意一个字符egrep a.b 文件名;表示匹配文件中a跟b之间有一个任意字符的行;
()小括号可以将正则表达式的一部分括起来组成一个单元(也就是一个组),可以对整个单元使用数量限定符([a-z]-[0-9]){1,3}:表示匹配”字母-数字“这样的格式的组合三次
[]匹配括号中的任意一个字符egrep [0-9] 文件名;表示匹配文件中含有0-9任意一个数字的行;
[^]表示否定括号中出现的字符,取反[ ^0-9]:表示匹配任意一位非数字字符;
\转义符,可以将普通字符转为特殊字符,将特殊字符转为普通字符,大多时候是用在将特殊字符的含义取消".$“如果前面没有加转义符,则表示匹配以任意一个字符结尾的行,加上转义字符之后表示匹配以”."结尾的行,也就是把“.“的特殊含义取消了,变成普通的”.”符号;
|连接两个子表达式,表示或的关系`a
[[:xxx:]]grep工具预定义的一些命名字符[[:digit:]]表示匹配一个数字[0-9],[[:alpha:]表示匹配一个英文字母[a-Z]
  • 示例
精确匹配  以a开头c结尾  中间任意  长度为三个字节的字符串
[root@xiongbinbin class04]# egrep "^a.c$" a.txt
abc
adc
a c
adc
a_c
a.c
aDc
aZc
a3c
a9c

模糊匹配  以cc结尾的字符串  因为$只能锚定单个字符,如果是一个字符串就需要用()来做定义
[root@xiongbinbin class04]# egrep "(cc)$" a.txt
gbcc
ccc
[root@xiongbinbin class04]#

精确匹配  以a开头c结尾  中间是a-z,0-9 长度为是三个字节的字符串
[root@xiongbinbin class04]# egrep "^a[a-z0-9]c$" a.txt
abc
adc
adc
a3c
a9c

精确匹配 以a或者b开头,c结尾的字符串
[root@xiongbinbin class04]# egrep "^(a|b)c$" a.txt
ac
bc

模糊匹配 以a开头c结尾 中间任意一个非字母之外的字符
[root@xiongbinbin class04]# egrep "^a[^a-zA-Z]c$" a.txt
a c
a_c
a.c
a3c
a9c

精确匹配以a开头c结尾 中间是.的字符串
[root@xiongbinbin class04]# egrep "^a\.c$" a.txt
a.c

3、数量限定符
  • 数量限定符:对前面的字符或者(字符串)出现的次数做限定说明
限定符功能举例
*某个字符后面加***表示该字符不出现或者出现多次**“^a*c$”
?某个字符后面加**?表示该字符出现一次或者不出现**“^ab?c$”
+某个字符后面加**+表示其前面的字符出现一次或多次,但必须至少出现一次**“^ab+c$”
{n,m}添加在某个字符或表达式后面后面,表示该字符或表达式后面最少出现n次,最多出现m次“^ab{1,2}c$”
{n}添加在某个字符或表达式后面后面,表示该字符或表达式后面正好出现n次mo{2}y、'[0-9]{ 2}
{n,}添加在某个字符或表达式后面,表示该字符或表达式出现不少于n次mo{2,}y、'[0-9]{2,}
  • 注意:egrep(grep-E)、awk使用{n}{n, }{n,m}匹配时"{}”前不用加"\",其他地方要加转义
    
  • 示例

精确匹配 以a开头 c 结尾 中间是有b或者没有b 长度不限的字符串
[root@xiongbinbin class04]# egrep "^ab*c$" a.txt
ac
abc
abbc

精确匹配 以a开头 c 结尾 中间是有b,至少出现一次 长度不限的字符串
[root@xiongbinbin class04]# egrep "^ab+c$" a.txt
abc
abbc

精确匹配 以a开头 c 结尾 中间是有b,最多出现一次 
[root@xiongbinbin class04]# egrep "^ab?c$" a.txt
ac
abc

精确匹配 以a开头 c结尾 中间是有b 至少出现2次,最多出现四次  长度不限的字符串
[root@xiongbinbin class04]# egrep "^ab{2,4}c$" a.txt
abbc
abbbc

精确匹配 以a开头 c结尾 中间是有b 刚好出现2次
[root@xiongbinbin class04]# egrep "^ab{2}c$" a.txt
abbc

4、POSIX字符
  • POSIX字符一次只匹配一个范围中的一个字节
  • 注意使用[[]],eg:[[:alnum:]],外面的[]是匹配字符,里面是POSIX字符本身的[]
特殊字符功能说明
[:alnum:]匹配任意字母字符0-9 a-z A-Z
[:alpha:]匹配任意字母,大写或小写
[:digit:]数字0-9
[:graph:]非空字符(非空格控制字符)
[:lower:]小写字母a-z
[:upper:]大写字母A-Z
[:cntrl:]控制字符
[:print:]非空字符(包括空格)
[:punct:]标点符号
[:blank:]空格和TAB字符
[:xdigit:]16进制数字
[:space:]所有空白字符(新行、空格、制表符)
  • ipv4地址匹配公式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ijIRDjr-1675659763810)(Linux-shell零基础入门到大师.assets/image-20221111113018041.png)]

((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))

八、sed命令

8.1、sed介绍
  • sed是linux中提供的一个外部命令,他是一个行(流)编辑器,非交互式的对文件内容进行增删改查的操作,使用者只能在命令行输入编辑命令,指定文件名,然后在屏幕上查看输出。
  • 他和文本编辑器有本质的区别
    • 文本编辑器:编辑对象是文件
    • 行编辑器:编辑对象是文件中的行内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mAPLKlfh-1675659763810)(Linux-shell零基础入门到大师.assets/image-20221111113935360.png)]

8.2、sed命令语法
1、语法:sed [options] ‘{command}[flags]’ [filename]
  • 参数概括说明
command说明:
a : 在匹配后面添加
i : 在匹配前面添加
d : 删除
s : 查找替换  字符串
c : 更改
y : 转换  N D P
P : 打印

命令选项options说明:
-e script : 将脚本中指定的命令添加到处理输入时执行的命令中  多条件,一行中要有多个命令操作,多个命令之间用 ; 隔开
-f script : 将文件中指定的命令添加到处理输入时执行的命令中;即从文件中读取编辑命令,适用于日常重复执行的场景
-n		  : 抑制自动输出
-i		  : 编辑文件的内容
-i.xxx	   : 修改时同时创建后缀名为.xxx的  备份文件。
-r		  : 使用扩展的正则表达式
!		  : 取反  (跟在模式条件后与shell有所区别)

flags说明:
数字 		: 表示新文本替换的模式
g	 	  : 表示用新文本替换现有文本的全部实例
p	 	  : 表示打印原始的内容
w file	  : 将替换的结果写入文件 

2、sed内部命令的说明
command说明:
a : 在匹配后面添加
i : 在匹配前面添加
d : 删除
s : 查找替换  字符串
c : 更改
y : 转换  N D P
P : 打印
  • 演示文档
[root@xiongbinbin class04]# cat sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.
1、文件内容增加操作a/i
  • 将数据追加到某个位置之后,使用命令a。
  • 将数据追加到某个位置之前,使用命令i,语法同a。
以a举例:
在sed_data的每行后追加一行新数据内容:append data "haha"
[root@xiongbinbin class04]# sed 'a\append data "haha"' sed_data
1 the quick brown fox jumps over the lazy dog.
append data "haha"
2 the quick brown fox jumps over the lazy dog.
append data "haha"
3 the quick brown fox jumps over the lazy dog.
append data "haha"
4 the quick brown fox jumps over the lazy dog.
append data "haha"
5 the quick brown fox jumps over the lazy dog.
append data "haha"

在第二行后新开一行追加数据:append data "haha"
[root@xiongbinbin class04]# sed '2a\append data "haha"' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
append data "haha"
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

在第二行到第四行每行后新开一行追加数据:append data "haha"
[root@xiongbinbin class04]# sed  '2,4a\append data "haha"' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
append data "haha"
3 the quick brown fox jumps over the lazy dog.
append data "haha"
4 the quick brown fox jumps over the lazy dog.
append data "haha"
5 the quick brown fox jumps over the lazy dog.

先匹配指定内容的行,再在匹配的行后面新开一行追加数据
[root@xiongbinbin class04]# sed  '/^3 the/a\append data "haha"' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
append data "haha"
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

注意:这里的'\'是转义,不是分割符的意思,不加\也是可以的
[root@xiongbinbin class04]# sed 'aappend data "haha"' sed_data
1 the quick brown fox jumps over the lazy dog.
append data "haha"
2 the quick brown fox jumps over the lazy dog.
append data "haha"
3 the quick brown fox jumps over the lazy dog.
append data "haha"
4 the quick brown fox jumps over the lazy dog.
append data "haha"
5 the quick brown fox jumps over the lazy dog.
append data "haha"

2、删除 d
删除文件中所有的行内容
[root@xiongbinbin class04]# sed 'd' sed_data
[root@xiongbinbin class04]#

删除指定的某一行
[root@xiongbinbin class04]# sed '2d' sed_data
1 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

删除指定的某几行
[root@xiongbinbin class04]# sed '2,4d' sed_data
1 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

匹配删除
[root@xiongbinbin class04]# sed '/^2 the/d' sed_data
1 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

3、替换 s
将文件中的每行中的dog替换成cat
[root@xiongbinbin class04]# sed 's/dog/cat/' sed_data
1 the quick brown fox jumps over the lazy cat.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy cat.
4 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy cat.

注意: 这里的'/' 可以是其他字符;如:@、#、$等

[root@xiongbinbin class04]# sed 's#dog#cat#' sed_data
1 the quick brown fox jumps over the lazy cat.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy cat.
4 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy cat.

只替换某一行中的字符串
[root@xiongbinbin class04]# sed '2s/dog/cat/' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

替换某个范围行的字符串
[root@xiongbinbin class04]# sed '2,4s/dog/cat/' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy cat.
4 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy dog.

匹配替换
[root@xiongbinbin class04]# sed '/^2 the/s/dog/cat/' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

4、修改 c
修改文件中所有行的内容
注意:这里的'\' 和a里面的一样也是转义的意思,不加也可以
[root@xiongbinbin class04]# sed 'c\haha' sed_data
haha
haha
haha
haha
haha

修改某一行的内容
1 the quick brown fox jumps over the lazy dog.
haha
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

修改某几行的内容
[root@xiongbinbin class04]# sed '2,4c\haha' sed_data
1 the quick brown fox jumps over the lazy dog.
haha
5 the quick brown fox jumps over the lazy dog.

匹配修改
[root@xiongbinbin class04]# sed '/^3 the/c\haha' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
haha
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

5、转换 y
将abc分别对应转换成CDF
[root@xiongbinbin class04]# sed 'y/abc/CDF/' sed_data
1 the quiFk Drown fox jumps over the lCzy dog.
2 the quiFk Drown fox jumps over the lCzy dog.
3 the quiFk Drown fox jumps over the lCzy dog.
4 the quiFk Drown fox jumps over the lCzy dog.
5 the quiFk Drown fox jumps over the lCzy dog.
注意:这里a-->C、b--->D、c--->F
  • 查看 p
查看文件中所有内容
[root@xiongbinbin class04]# sed 'p' sed_data
1 the quick brown fox jumps over the lazy dog.
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.
注意:这里打印了两次,是因为sed本身就会将匹配的内容默认输出到屏幕,这里p又将匹配到放在内存里的内容打印出来了

指定打印某一行
[root@xiongbinbin class04]# sed '2p' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

指定打印某几行
[root@xiongbinbin class04]# sed '2,4p' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

匹配打印
[root@xiongbinbin class04]# sed '/^2 the/p' sed_data
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.


3、命令选项(options)说明
  • 命令选项是对sed命令的增强
命令选项:
-e script : 将脚本中指定的命令添加到处理输入时执行的命令中  多条件,一行中要有多个命令操作,多个命令之间用 ; 隔开
-f script : 将文件中指定的命令添加到处理输入时执行的命令中;即从文件中读取编辑命令,适用于日常重复执行的场景
-n		  : 抑制自动输出
-i		  : 编辑文件的内容
-i.xxx	   : 修改时同时创建后缀名为.xxx的  备份文件。
-r		  : 使用扩展的正则表达式
!		  : 取反  (跟在模式条件后与shell有所区别)
1、在命令行中使用多个命令:-e
将brown替换成green,dog替换成cat
 [root@xiongbinbin class04]# sed -e 's/brown/green/;s/dog/cat/' sed_data
1 the quick green fox jumps over the lazy cat.
2 the quick green fox jumps over the lazy cat.
3 the quick green fox jumps over the lazy cat.
4 the quick green fox jumps over the lazy cat.
5 the quick green fox jumps over the lazy cat.

2、从文件中读取编辑命令 -f
先将要执行的命令写入文件sedfile中,然后利用 -f 读取文件中的命令执行操作
[root@xiongbinbin class04]# cat sedfile
s/brown/green/
s/dog/cat/
s/fox/elephant/
[root@xiongbinbin class04]# sed -f sedfile sed_data
1 the quick green elephant jumps over the lazy cat.
2 the quick green elephant jumps over the lazy cat.
3 the quick green elephant jumps over the lazy cat.
4 the quick green elephant jumps over the lazy cat.
5 the quick green elephant jumps over the lazy cat.
3、抑制内存输出 -n
打印文件中的第二行到最后一行  $ 最后的意思
[root@xiongbinbin class04]# sed -n '2,$p' sed_data
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

打印文件中的第三行的内容
[root@xiongbinbin class04]# sed -n '3p' sed_data
3 the quick brown fox jumps over the lazy dog.

4、使用正则表达式 -r
打印文件中以字符串"3 the"开头的内容
[root@xiongbinbin class04]# sed -r -n '/^(3 the)/p' sed_data
3 the quick brown fox jumps over the lazy dog.

如果不适用-r 则无法匹配
[root@xiongbinbin class04]# sed  -n '/^(3 the)/p' sed_data
[root@xiongbinbin class04]#

5、编辑文件的内容 -i / -i.xxx
  • 从上面的例子可以看出,上述中的修改都是在缓存中完成的,并没有真正的修改文件中的内容,如果要修改文件本身的内容就需要用-i命令选项
  • -i 是直接修改文件内容
  • -i.xxx 修改之前会先做备份
[root@xiongbinbin class04]# sed -i.bak 's/brown/green/' sed_data
[root@xiongbinbin class04]# ll
total 28
-rw-r--r-- 1 root root 2626 Nov 11 10:58 a.txt
-rw-r--r-- 1 root root  379 Nov 10 20:47 case_1.sh
-rw-r--r-- 1 root root  322 Nov 10 18:05 fun1.sh
-rw-r--r-- 1 root root  395 Nov 10 19:06 fun2.sh
-rw-r--r-- 1 root root  235 Nov 11 14:51 sed_data
-rw-r--r-- 1 root root  235 Nov 11 12:07 sed_data.bak
-rw-r--r-- 1 root root   42 Nov 11 14:07 sedfile
[root@xiongbinbin class04]# cat sed_data
1 the quick green fox jumps over the lazy dog.
2 the quick green fox jumps over the lazy dog.
3 the quick green fox jumps over the lazy dog.
4 the quick green fox jumps over the lazy dog.
5 the quick green fox jumps over the lazy dog.
[root@xiongbinbin class04]# cat sed_data.bak
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

3、标志
  • 在sed命令中,标志是对sed中的内部命令做补充说明
flags说明:
数字 		: 表示新文本替换的模式
g	 	  : 表示用新文本替换现有文本的全部实例
p	 	  : 表示打印原始的内容
w file	  : 将替换的结果写入文件 
演示文档
[root@xiongbinbin class04]# cat sed_data2
1 the quick green fox jumps over the lazy dog.dog
2 the quick green fox jumps over the lazy dog.dog
3 the quick green fox jumps over the lazy dog.dog
4 the quick green fox jumps over the lazy dog.dog
5 the quick green fox jumps over the lazy dog.dog
1、数字标志
  • 此标志是一个非零正数,默认情况下,执行替换的时候,如果一行中有多个符合的字符串,如果没有标志位定义,那么只会替换每行中第一个字符串,其他的就被忽略掉了,为了能精确替换,可以使用数字位做定义。
替换一行中的第二处dog为cat
[root@xiongbinbin class04]# sed 's/dog/cat/2' sed_data2
1 the quick green fox jumps over the lazy dog.cat
2 the quick green fox jumps over the lazy dog.cat
3 the quick green fox jumps over the lazy dog.cat
4 the quick green fox jumps over the lazy dog.cat
5 the quick green fox jumps over the lazy dog.cat

2、g标志
  • 将一行中的所有符合的字符串全部执行替换
[root@xiongbinbin class04]# sed 's/dog/cat/g' sed_data2
1 the quick green fox jumps over the lazy cat.cat
2 the quick green fox jumps over the lazy cat.cat
3 the quick green fox jumps over the lazy cat.cat
4 the quick green fox jumps over the lazy cat.cat
5 the quick green fox jumps over the lazy cat.cat

九、awk命令

9.1、awk介绍
  • 行编辑器,负责数据的截取和处理

  • awk是一种可以处理数据、产生格式化报表的语言,功能十分强大。awk认为文件中的每一行是一条记录,记录与记录的分隔符为换行符,每一列是一个字段 字段与字段的分隔符默认是一个或多个空格或tab制表符。

  • awk的工作方式是读取数据,将每一行数据视为一条记录(record)每条记录以字段分割符分成若干字段,然后输出各个字段的值。

总结如下:
	awk : 行编辑器,负责数据的截取和处理
	行 : 叫做记录,记录与记录的分割符是换行符,即回车
	列 : 叫做字段,字段与字段的分隔符是空格或table
9.2、awk语法
  • awk [options] ‘[BEGIN] {program} [END]’ [filename]
常用命令选项:
	-F fs 	: 指定输入数据字段之间的分隔符   默认是空格
	-f file	: 指定读取程序的文件名
	-v var=value	: 定义awk程序中使用的变量和默认值

注意:awk 程序program由左大括号和右大括号定义。程序命令必须放在两个大括号之间。由于awk命令行假定程序是单文本字符串,所以必须将程序包括在单引号内。
	1):程序必须放在大括号内
	2):程序必须要用单引号引起来

awk程序运行优先级是:
	1)BEGIN: 在开始处理数据流之前执行,可选项
	2)program: 如何处理数据,必选项
	3)END: 处理完数据流后执行,可选项
9.3、awk基本应用
  • awk命令中常用的相关的内置变量
awk命令中相关的内置变量
	$0 : 表示整行文本
	$1 : 表示文本行中的第一列字段
	$2 : 表示文本行中的第二列字段
	$N : 表示文本行中的第N列字段
	NF  : 表示文本行中字段的数量变量
	$NF : 表示文本行中的最后一列字段
	NR	: 每行的记录号,多文件记录递增
	FNR : 与NR类似,不过多文件记录不递增,每个文件都从1开始
	FS	: BEGIN时定义分隔符
	RS	: 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
	OFS	 : 输出字段分隔符, 默认也是空格,可以改为制表符等
	ORS	 : 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
  • 演示文件准备
[root@xiongbinbin class05]# cat data
1 the quick brown fox jumps over the lazy cat.dog
2 the quick brown fox jumps over the lazy cat.dog
3 the quick brown fox         jumps over the lazy cat.dog
4 the quick brown fox jumps over the lazy cat.dog
5 the quick brown fox jumps over the lazy cat.dog
1、awk对字段(列)的提取
打印文件的内容
注意:{print $0} == {print}
[root@xiongbinbin class05]# awk '{print $0}' data
1 the quick brown fox jumps over the lazy cat.dog
2 the quick brown fox jumps over the lazy cat.dog
3 the quick brown fox         jumps over the lazy cat.dog
4 the quick brown fox jumps over the lazy cat.dog
5 the quick brown fox jumps over the lazy cat.dog

[root@xiongbinbin class05]# awk '{print}' data
1 the quick brown fox jumps over the lazy cat.dog
2 the quick brown fox jumps over the lazy cat.dog
3 the quick brown fox         jumps over the lazy cat.dog
4 the quick brown fox jumps over the lazy cat.dog
5 the quick brown fox jumps over the lazy cat.dog

打印指定的列,列与列之间用逗号隔开
[root@xiongbinbin class05]# awk '{print $1,$5}' data
1 fox
2 fox
3 fox
4 fox
5 fox

打印最后一列
[root@xiongbinbin class05]# awk '{print $NF}' data
cat.dog
cat.dog
cat.dog
cat.dog
cat.dog

打印多列的数据,并指定输出数据之间的分隔符
[root@xiongbinbin class05]# awk '{print $1 "-" $5}' data
1-fox
2-fox
3-fox
4-fox
5-fox

指定输入数据字段之间的分隔符 -F
[root@xiongbinbin class05]# awk -F "." '{print $NF}' data
dog
dog
dog
dog
dog

2、awk对记录(行)的提取
  • 记录(行)的提取方法有两种
    • 通过行号:NR
    • 通过正则匹配
提取第三行数据
	指定行号
[root@xiongbinbin class05]# awk 'NR=="3"{print}' data
3 the quick brown fox         jumps over the lazy cat.dog
[root@xiongbinbin class05]#
	指定第一行字段精确匹配
[root@xiongbinbin class05]# awk '$1=="3"{print}' data
3 the quick brown fox         jumps over the lazy cat.dog
[root@xiongbinbin class05]#

3、awk对字符串的提取
  • 记录和字段的汇合点就是字符串
打印第三行的第六个字段
[root@xiongbinbin class05]# awk 'NR=="3"{print $6}' data
jumps
[root@xiongbinbin class05]#

9.4、awk程序的优先级
  • BEGIN是优先级最高的代码块,是在program之前执行的,不需要数据源,因为不涉及到任何数据的处理,也不依赖与program代码块;program是对数据流干什么,是必选代码块,也是默认代码块。所以在执行时必须提供数据源;END是处理完数据流后的操作,如果需要执行END代码块,就必须需要program的支持,单个无法执行。
BEGIN : 处理数据源之前干什么		不需要数据源就可以执行
PROGRAM : 对数据源干什么			需要数据源
END	  : 处理完数据后干什么		 需要program 需要数据源
  • 示例
执行优先级演示
[root@xiongbinbin class05]# awk 'BEGIN{print "hello root"}{print $0}END{print "bye root"}' data
hello root
1 the quick brown fox jumps over the lazy cat.dog
2 the quick brown fox jumps over the lazy cat.dog
3 the quick brown fox         jumps over the lazy cat.dog
4 the quick brown fox jumps over the lazy cat.dog
5 the quick brown fox jumps over the lazy cat.dog
bye root
[root@xiongbinbin class05]#

BEGIN 不需要数据源,直接执行
[root@xiongbinbin class05]# awk 'BEGIN{print "hello everyone!"}'
hello everyone!
[root@xiongbinbin class05]#

END 依赖数据源,依赖program
[root@xiongbinbin class05]# awk 'NR=="1"{print $1}END{print "hello everyone!"}' data
1
hello everyone!
[root@xiongbinbin class05]#


9.5、awk高级应用
  • awk是一门语言,那么就符合语言的特性。除了可以定义变量外,还可以定义数组,还可以进行运算,流程控制等
1、awk定义变量和数组
  • 定义变量
使用 -v
[root@xiongbinbin class05]# awk -v name="hahaha" 'BEGIN{print name}'
hahaha
[root@xiongbinbin class05]#

在程序中定义
[root@xiongbinbin class05]# awk 'BEGIN{name="hahaha";print name}'
hahaha
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{name="hahaha";print "name1:" name}{print $0}END{name="heihei";print "name2:" name}' data
name1:hahaha
1 the quick brown fox jumps over the lazy cat.dog
2 the quick brown fox jumps over the lazy cat.dog
3 the quick brown fox         jumps over the lazy cat.dog
4 the quick brown fox jumps over the lazy cat.dog
5 the quick brown fox jumps over the lazy cat.dog
name2:heihei

  • 定义数组
[root@xiongbinbin class05]# awk 'BEGIN{array[0]=100;array[1]=200;print array[0],array[1]}'
100 200
[root@xiongbinbin class05]#

2、awk运算
  • 常见的运算
赋值运算 : =
比较运算 : > , >= , == , < , <= , !=
数学运算 : + - * / %  **  ++ --
逻辑运算 : && || !
匹配运算 : 
	模糊匹配 : ~ !~  
	精确匹配 : ==  !=
  • 赋值运算,主要对变量或者数组赋值
对变量赋值
[root@xiongbinbin class05]# awk -v name="zhangsan" 'BEGIN{print name}'
zhangsan
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{name="hahaha";print name}'
hahaha
[root@xiongbinbin class05]#

对数组赋值
[root@xiongbinbin class05]# awk 'BEGIN{array[0]=100;print array[0]}'                     100
[root@xiongbinbin class05]#

  • 比较运算
    • 如果比较的是字符串,则按照ascii编码顺序表比较。如果结果返回为真则用1表示,返回为假则用0表示。
[root@xiongbinbin class05]# awk 'BEGIN{print "a" >= "b"}'
0
[root@xiongbinbin class05]# awk 'BEGIN{print "a" <= "b"}'
1

[root@xiongbinbin class05]# awk 'BEGIN{print 1==1}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print 1 != 1}'
0

  • 数学运算
[root@xiongbinbin class05]# awk 'BEGIN{print 1 + 1}'
2
[root@xiongbinbin class05]# awk 'BEGIN{print 1 - 1}'
0
[root@xiongbinbin class05]# awk 'BEGIN{print 2 * 2}'
4
[root@xiongbinbin class05]# awk 'BEGIN{print 2 / 2}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print 2 ** 2}'
4
[root@xiongbinbin class05]# awk 'BEGIN{print 3 % 2}'
1
[root@xiongbinbin class05]#
[root@xiongbinbin class05]# awk -v 'count=0' 'BEGIN{count ++;print count}'
1
[root@xiongbinbin class05]# awk -v 'count=0' 'BEGIN{count --;print count}'
-1
[root@xiongbinbin class05]# awk -v 'count=0' 'BEGIN{count +=2;print count}'
2
[root@xiongbinbin class05]# awk -v 'count=0' 'BEGIN{count -=2;print count}'
-2

  • 逻辑运算
[root@xiongbinbin class05]# awk 'BEGIN{print 100 >= 10 && 100 >= 50}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print 100 < 10 || 100 >= 50}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print 100 < 10 && 100 >= 50}'
0
[root@xiongbinbin class05]# awk 'BEGIN{print 100 >= 20}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print !(100 >= 20)}'
0

  • 匹配运算
    • 精确匹配:==、!=
    • 模糊匹配:、!
[root@xiongbinbin class05]# awk -F : '$1=="root"{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@xiongbinbin class05]# awk -F : '$1 ~ "te"{print}' /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
test123:x:1000:1000:test123:/home/test123:/bin/bash
gluster:x:996:992:GlusterFS daemons:/run/gluster:/sbin/nologin
[root@xiongbinbin class05]# awk -F : '$1 ~ "^te"{print}' /etc/passwd
test123:x:1000:1000:test123:/home/test123:/bin/bash
[root@xiongbinbin class05]#

3、awk的内置环境变量
  • 常见的内置变量
变量描述
FIELDWIDTHS以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
FS输入字段分隔符号 数据源的字段分符 ; 类似 -F
OFS输出字段分隔符号
RS输入记录分隔符;即会改变输入数据源中行的分隔符,源数据文件不会改变
ORS输出记录分隔符;打印到屏幕的
[root@xiongbinbin class05]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}' /etc/passwd
root: x: 0:0:root
[root@xiongbinbin class05]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' /etc/passwd
root-0-/bin/bash


[root@xiongbinbin class05]# cat test
1
2
3
4
5
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{RS="-"}{print $1,$2,$3,$4,$5}' test
1 2 3 4 5
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{ORS="@@@"}{print $1,$2,$3,$4,$5}' test
1    @@@2    @@@3    @@@4    @@@5    @@@[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{RS="-";ORS="@@@"}{print $1,$2,$3,$4,$5}' test
1 2 3 4 5@@@[root@xiongbinbin class05]#


RS的应用:这里将每组数据以'空行'作为每个记录的分隔符,这样就把每组数据(三行数据为一组)处理成一行,进行处理取值
[root@xiongbinbin class05]# cat contact
tom
shanghai
010-123456

jack
nanjing
020-123456

marry
guangzhou
030-123456
[root@xiongbinbin class05]# awk 'BEGIN{RS=""}{print $1,$NF}' contact
tom 010-123456
jack 020-123456
marry 030-123456
[root@xiongbinbin class05]#

4、流程控制
  • if判断
[root@xiongbinbin class05]# cat test
1
2
3
4
5
6
7
8
9

[root@xiongbinbin class05]# awk '{if($1 > 5) print $0}' test
6
7
8
9

[root@xiongbinbin class05]# awk '{if($1 > 5) print $1*2 ;else print $1/2}' test
0.5
1
1.5
2
2.5
12
14
16
18

  • for循环
[root@xiongbinbin class05]# awk '{sum=0;for(i=1;i<4;i++){sum +=$i} print sum}' num
130
140
180

  • while循环
[root@xiongbinbin class05]# awk '{sum=0;i=1;while(i<4){sum +=$i;i++}print sum }' num
130
140
180

  • do…while
[root@xiongbinbin class05]# cat num
20 50 60
30 40 70
50 70 60

# 将每行中的数据进行累加,和大于或等于70,就停止累加
[root@xiongbinbin class05]# awk '{sum=0;i=1;do{sum+=$i;i++}while(sum<=70)print sum}' num
130
140
120

  • 循环控制
    • break跳出循环,继续执行后面的语句
[root@xiongbinbin class05]# cat num
20 50 60
30 40 70
50 70 60

[root@xiongbinbin class05]# awk '{sum=0;i=1;while(i<4){sum +=$i;i++;if(sum >=70)break}print sum}' num
70
70
120

扩展

1、mailx 邮件服务
1.1、准备工作
  • 打开邮箱设置,开启pop3/smtp服务和imap/smtp服务
  • 安装mailx: yum install -y mailx
1.2、 配置
设置/etc/mail.rc文件,在文件尾追加如下配置

set from=xxx@qq.com						#发件人邮箱
set smtp=smtp.qq.com
set smtp-auth-user=xxx@qq.com			 #登录用户名
set smtp-auth-password=xxxx				 #邮箱授权码,在QQ邮箱设置界面发短信生成
set smtp-auth=login						#登录
1.3、发送邮件
语法:
	mail -s "邮件主题" 收件人邮箱 邮件正文
$ echo "Hello Maxwell,这里是邮件正文." | mail -s "邮件主题" xxx@qq.com(收件人邮箱)
05]# awk 'BEGIN{print 100 >= 20}'
1
[root@xiongbinbin class05]# awk 'BEGIN{print !(100 >= 20)}'
0

  • 匹配运算
    • 精确匹配:==、!=
    • 模糊匹配:、!
[root@xiongbinbin class05]# awk -F : '$1=="root"{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@xiongbinbin class05]# awk -F : '$1 ~ "te"{print}' /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
test123:x:1000:1000:test123:/home/test123:/bin/bash
gluster:x:996:992:GlusterFS daemons:/run/gluster:/sbin/nologin
[root@xiongbinbin class05]# awk -F : '$1 ~ "^te"{print}' /etc/passwd
test123:x:1000:1000:test123:/home/test123:/bin/bash
[root@xiongbinbin class05]#

3、awk的内置环境变量
  • 常见的内置变量
变量描述
FIELDWIDTHS以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
FS输入字段分隔符号 数据源的字段分符 ; 类似 -F
OFS输出字段分隔符号
RS输入记录分隔符;即会改变输入数据源中行的分隔符,源数据文件不会改变
ORS输出记录分隔符;打印到屏幕的
[root@xiongbinbin class05]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}' /etc/passwd
root: x: 0:0:root
[root@xiongbinbin class05]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' /etc/passwd
root-0-/bin/bash


[root@xiongbinbin class05]# cat test
1
2
3
4
5
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{RS="-"}{print $1,$2,$3,$4,$5}' test
1 2 3 4 5
[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{ORS="@@@"}{print $1,$2,$3,$4,$5}' test
1    @@@2    @@@3    @@@4    @@@5    @@@[root@xiongbinbin class05]#

[root@xiongbinbin class05]# awk 'BEGIN{RS="-";ORS="@@@"}{print $1,$2,$3,$4,$5}' test
1 2 3 4 5@@@[root@xiongbinbin class05]#


RS的应用:这里将每组数据以'空行'作为每个记录的分隔符,这样就把每组数据(三行数据为一组)处理成一行,进行处理取值
[root@xiongbinbin class05]# cat contact
tom
shanghai
010-123456

jack
nanjing
020-123456

marry
guangzhou
030-123456
[root@xiongbinbin class05]# awk 'BEGIN{RS=""}{print $1,$NF}' contact
tom 010-123456
jack 020-123456
marry 030-123456
[root@xiongbinbin class05]#

4、流程控制
  • if判断
[root@xiongbinbin class05]# cat test
1
2
3
4
5
6
7
8
9

[root@xiongbinbin class05]# awk '{if($1 > 5) print $0}' test
6
7
8
9

[root@xiongbinbin class05]# awk '{if($1 > 5) print $1*2 ;else print $1/2}' test
0.5
1
1.5
2
2.5
12
14
16
18

  • for循环
[root@xiongbinbin class05]# awk '{sum=0;for(i=1;i<4;i++){sum +=$i} print sum}' num
130
140
180

  • while循环
[root@xiongbinbin class05]# awk '{sum=0;i=1;while(i<4){sum +=$i;i++}print sum }' num
130
140
180

  • do…while
[root@xiongbinbin class05]# cat num
20 50 60
30 40 70
50 70 60

# 将每行中的数据进行累加,和大于或等于70,就停止累加
[root@xiongbinbin class05]# awk '{sum=0;i=1;do{sum+=$i;i++}while(sum<=70)print sum}' num
130
140
120

  • 循环控制
    • break跳出循环,继续执行后面的语句
[root@xiongbinbin class05]# cat num
20 50 60
30 40 70
50 70 60

[root@xiongbinbin class05]# awk '{sum=0;i=1;while(i<4){sum +=$i;i++;if(sum >=70)break}print sum}' num
70
70
120

扩展

1、mailx 邮件服务
1.1、准备工作
  • 打开邮箱设置,开启pop3/smtp服务和imap/smtp服务
  • 安装mailx: yum install -y mailx
1.2、 配置
设置/etc/mail.rc文件,在文件尾追加如下配置

set from=xxx@qq.com						#发件人邮箱
set smtp=smtp.qq.com
set smtp-auth-user=xxx@qq.com			 #登录用户名
set smtp-auth-password=xxxx				 #邮箱授权码,在QQ邮箱设置界面发短信生成
set smtp-auth=login						#登录
1.3、发送邮件
语法:
	mail -s "邮件主题" 收件人邮箱 邮件正文
$ echo "Hello Maxwell,这里是邮件正文." | mail -s "邮件主题" xxx@qq.com(收件人邮箱)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值