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:脚本路径
四、变量
- 计算机程序在运行的过程中需要将一些数据存放在内存中,需要的时候读出来,计算机内存在计算机中扮演桥梁的作用;
-
- 将数据从硬盘中读出存入内存,从内存读出给CPU
-
- 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(收件人邮箱)