shell编程-正则表达式与文本处理器sedawk
Posted 可乐卷儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell编程-正则表达式与文本处理器sedawk相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、正则表达式
1、定义
- 又称正规表达式、常规表达式
- 使用字符串来描述、匹配一系列符合某个规则的字符串
- 正则表达式组成
- 普通字符
- 大小写字母、数字、标点符合及其一些其他符号
- 源字符
- 在正则表达式中具有特殊意义的专用字符
- 普通字符
2、正常表达式层次
2.1、基础正则表达式
基础正则表达式即常用的正则表达式部分
除了普通字符外,常见的以下元字符
\\ :转义符;\\n:换行;!:非
^:匹配以...开头
$:匹配以...结尾
^$:匹配空格
.:匹配出\\n(换行)之外的任意的一个字符
*:取决于前面一个字符,代表前面一个字符0次或多次
.*:任意长度的字符,*取决于.的字符
[ ]:匹配指定范围内的单个或多个字符
[^]:匹配任意不在列表中的单个或一组字符;是区分大小写的
^[]:匹配指定范围内的单个或多个字符开头
^[^]:匹配任意不在列表中的单个或一组字符
\\{n\\}:匹配前面的字符出现n次
\\{n,\\}:匹配前面的字符至少n次
\\{,m\\}:匹配前一个字符最多出现m次
\\{n,m}:匹配前面的字符n到m次
\\< :匹配以....开头的行
\\> :匹配以....结尾的行
\\<......\\>:匹配某一个单词的行;精确匹配
实例
a-zA-Z:所有大小写字母
a-zA-Z0-9:所有大小写字母和数字
echo ABC/0 | grep [ ^a-zA-Z0-9] ## 匹配出特殊字符
\\{n,m}:匹配前面的字符n到m次
\\{n\\}:匹配前面的字符出现n次
echo good | grep “go{1,3}d”
echo god | grep “go{1}d”
\\{n,\\}:匹配前面的字符至少n次
2.2、扩展正则表达式
扩展正则表达式是对基础正则表达式的扩充深化
扩展元字符如下
+:匹配前面字符至少1次以上;精确匹配
?:匹配前面字符0次或者1次
():将括号中的字符串作为一个整体
|:或
{n}:前一个字符重复n次
{n,}:前一个字符至少重复n次
{n,m}:前一个字符出现n-m次
查找网卡配置文件里面的ip地址
文本处理器三大剑客:grep、sed、awk;前面已经详细讲解了grep,这里就不做介绍了
二、文本处理器-sed
1、定义
sed 命令:按行操作,与单引号一起使用‘’;利用脚本来处理文本文件。无交互式的修改替换文件,它可以依照脚本的指令来处理、编辑文本文件。主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。
2、工作原理
- 读入新的一行内容到缓存空间;
- 从指定的操作指令中取出第一条指令,判断是否匹配pattern(模式);
- 如果不匹配,则忽略后续的编辑命令,回到第2步继续取出下一条指令;
- 如果匹配,则针对缓存的行执行后续的编辑命令;完成后,回到第2步继续取出下一条指令;
- 当所有指令都应用之后,输出缓存行的内容;回到第1步继续读入下一行内容;
- 当所有行都处理完之后,结束
3、命令格式
sed 选项 模式匹配 文件名
4、常用选项
常用选项 | 含义 |
---|---|
-e | 进行多次编辑 |
-n | 取消默认输出 |
-f | 指定sed文件名 |
-i | 直接在源文件中修改 |
-r | 使用扩展正则表达式 |
命令动作 | 含义 |
---|---|
p | 打印输出 |
d | 删除指定行 |
a | 在指定行后面插入内容 |
r | 读入其他文件内容到当前文件,并不会保存 |
w | 指定当前文件的内容写入另一个文件 |
c | 替换整行 |
s | 搜索替换(局部) |
s/ /g | 搜索替换(全局) |
s/ /i | 不区分大小写替换 |
= | 打印行号 |
i | 更改源文件 |
1. 打印输出-“-n与p”
-n #取消默认输出
p #打印输出 两者一般结合使用
sed ‘p’ yy.txt ## 逐行打印,但是会打印2遍,一般p与-n结合使用
sed -n ‘1p’ yy.txt ## ‘1p’:打印第一行
sed -n ‘3p’ yy.txt ## ‘3p’:打印第三行
sed -n ‘1,3p’ yy.txt ## “,”逗号是连续,‘1,3p’:打印1-3行
sed -n ‘1,+4p’ ##打印1-4行;其中’1,+4p’=‘1,4p’
sed -n ‘0~2p’:打印偶数行;从第一行开始,间隔2行打印
sed -n ‘1~2p’:打印奇数行;从第0行开始,间隔2行打印
cat -n yy.txt | sed -n ‘1~2p’
sed -n ‘$p’:打印最后一行
sed -n ‘2p;3p’ ##打印第二行和第三行;分号“;”是间隔
sed -n ‘/^root/p’ ##打印root开头的行
sed -n ‘/bash$/p’ ##打印bash结尾的行
sed -n ‘/^root|bash$/p’ ##打印root开头bash结尾的行;这里的“|”代表或,需要使用转义符“/”
sed -n ‘/^$/p’ yy.txt #打印空格
‘/ /p’:打印出有空格的行
打印出/bin/bash的行
2. 使用扩展正则表达式-“-r”
sed默认不支持扩展正则,如果要支持,需要加-r选项
-r:使用扩展正则表达式;匹配扩展元字符时,使用此选项,无须使用转义符
3. 多条命令时使用-“-e:或”
sed -ne ‘/^root/p’ -e ‘/nologin$/p’ yy.txt #打印yy.txt文件内root开头或者nologin结尾的行
sed -ne ‘2p’ -e ‘4p’ yy.txt ##打印第二行或者第四行
4. 删除-“d”
'd' ##删除指定行;精确匹配字母大小写
'Id' ##删除指定行;忽略字母大小写
'$d':删除最后一行
cat -n yy.txt | sed ‘4d’ ##删除第四行
cat -n yy.txt | sed ‘/root/d’ ##删除root的行
5. 搜索替换-"s"
可以自定义分隔符;把字符串内的某些字符替换
sed -n ‘s#/bin/bash#bbb#p’ yy.txt
sed -n ‘s,/bin/bash#bbb,p’ yy.txt
sed -n ‘s@/bin/bash#bbb@p’ yy.txt
sed -n ‘s#/bin/bash#/sbin/nologin#p’ yy.txt
's':局部替换
'g':全局替换
's/ /i':不区分大小写 或者I(大写):不区分大小写
‘s/^#/ /p’:#开头的行替换成空格
给12两行开头替换成#
&符号;&=root,root前面需要加#
():当做位置变量使用,当有多个字符需要匹配时,括号内容保留替换
echo hello world gg | sed -nr ‘s/(hello) (world) (gg)/\\2 \\3 \\1/p’
echo hello world gg | sed -nr ‘s/(hello) (world)/\\2 the \\1/p’
6. 替换整行-‘c’
后面所有的内容识别成整体的内容
sed ‘/root/chello eorld;3p’ zz.txt :root替换成hello world;3p
7. 打印行号-“=”
sed ‘=’ yy.txt #打印文件的行号
‘$=’:最后一行
sed是逐行匹配
打印第三行内容和最后一行
sed -n ‘2=;3p’ yy.txt ##打印第二行行号和第三行内容
打印前五行
8. 增加内容-“a”“i”
‘a’:某一行的下面
'i':某一行的上面
'1a':在第一行后面插入
添加ip地址
以root开头后面插入ip地址
1-3行插入ip地址
9. 更改源文件-“-i”
-i.bak:备份源原件,并更改源文件内容
10. 插入其他文件内容
‘r’:读入其他文件内容到当前文件,并不会保存
‘1r’:第一行后面插入
‘$r’:最后一行插入
‘3r’:第三行后面插入
sed ‘3r /etc/hosts’ yy.txt 在yy.txt第三行插入/etc/hosts
11. 写入另一个文件-“w”
指定当前文件的内容写入另一个文件,再次追加其他文件内容会覆盖掉原本的内容
zz.txt的第一行写入/etc/hosts
5、通过调用文件执行操作-“-f”
新建一个sed脚本
开头写
#!/bin/sed -f
只需要把模式匹配内容写入
脚本内容可以逐行写入,若要在一行,中间分号“;”间隔
sed -f sed.sh p.txt
三、文本处理器-awk
1、概述
AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作数据可以来自标准输入也可以是管道或文件;缺点是不能替换,修改文件
20世纪70年代诞生于贝尔实验室,现在centos7用 的是gawk
之所以叫AWK是因为其取了三位创始人Alfred Aho, Peter Weinberger, 和Brian Kernighan 的Family Name的首字符。
2、工作原理
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次
格式:
awk关键字 选项 命令部分 '{xxxxxx}'
awk ‘{print}’ p.txt ##打印p.txt文本文件所有行
3、内置变量
$0:代表整行
$1:代表第一列
$2:代表第二列
$n:n代表数字1/2/3....;位置变量n
NF:列数,打印每行有多少列
NR:显示行号
FS:指定分隔符,默认为空白字符
OFS:定义了输出时的分隔符号,以什么分隔指定文件
RS:指定切割行的符号
ORS:指定什么连接行,指定输出的换行符
-F: ##指定分隔符
默认以空格或tab键作为分隔符分隔行
脚本文件加入两行带有空格和tab键的内容
3.1、变量实例
1. $1:位置变量1
awk -F: ‘{print $1}’ p.txt ##指定分隔符分号打印
awk -F/ ‘{print $1}’ p.txt ##指定分隔符/
awk -Fx ‘{print $1}’ p.txt ##指定分隔符x
打印多列;内置变量中间加逗号“,”
awk -F: ‘{print $1,$2}’ p.txt ##分号分隔符打印2列
内置变量中间加双引号“ ”,双引号内可任意设置符号
awk -F: ‘{print $1" " $2}’ p.txt
awk -F: ‘{print $1"–" $2}’ p.txt ##双引号加–
双引号内加入制表符 :\\t
打印用户名的root的uid是0
awk -F: ‘{print “用户名”$1"的uid是"$3}’ p.txt
2. $0:代表整行
awk -F: ‘{print $0}’ p.txt #以分隔符:打印整行
awk -F: ‘{print $0,$1,$2}’ p.txt ##打印整行的基础上,打印第一列和第二列
3. NF:列数,打印每行有多少列
awk -F: ‘{print NF}’ p.txt
$NF ##打印最后一列
awk -F: ‘{print $NF}’ p.txt
4. NR:显示行号
awk -F: ‘{print NR}’ p.txt
awk -F: ‘{print NR,$0}’ p.txt ##打印行号并输出行号;友好显示
也可以用于备份,写入其他文件
-F/NR/NF 综合实例 awk -F: '{print NR"\\t"$0}' p.txt ##打印整行并输出行号 awk -F[:/] '{print NF}' p.txt ##以:和/分割,并显示列数
以bin开头的那一行第一列
awk -F: ‘/^bin/{print $1}’ p.txt
awk -F: ‘/sbin/{print $0}’ p.txt ##包含sbin的行
awk -F: ‘/sbin/{print NR,$0}’ yy.txt ##打印包含sbin,显示行号打印整行
awk -F: ‘/sync$/{print NR,$0}’ yy.txt ##打印snyc结尾,显示行号,打印整行
awk -F: ‘/[oa]/{print NR,$0}’ yy.txt ##打印包含o或者a,显示行号,打印整行
3.2、awk的流程控制BEGIN和END
逐行执行开始之前执行什么任务,结束之后再执行什么任务,用BEGIN、END
BEGIN:用来做初始化操作,仅在读取数据记录之前执行一次
END:用来做汇总操作,仅在读取完数据记录之后执行一次
- BEGIN
- 可以直接做运算
[root@klj ~]# awk 'BEGIN{print 1+1}'
2
[root@klj ~]# awk 'BEGIN{print 1-1}'
0
[root@klj ~]# awk 'BEGIN{print 2**3}'
8
[root@klj ~]# awk 'BEGIN{print 2/3}'
0.666667
[root@klj ~]# awk 'BEGIN{print 2%3}'
2
- 使用变量时
[root@klj ~]# x=2
[root@klj ~]# awk 'BEGIN{print '$x'}'
2
[root@klj ~]# awk 'BEGIN{print "'$x'"}'
2
[root@klj ~]# awk 'BEGIN{x=2;x++;print x}'
3
[root@klj ~]# awk 'BEGIN{;x++;print x}' ##没有给x赋值,默认是0
1
- END
awk ‘END{print NR,$0}’ p.txt ##打印最后一整行
awk ‘BEGIN{FS=":"}{print $1}’ p.txt ##开始时定义分隔符为冒号,打印第一列
awk ‘BEGIN{RS=" "}{print}’ p.txt ##RS:以回撤分隔
awk ‘BEGIN{ORS=" "}{print}’ p.txt ##ORS:以空格分隔
awk ‘BEGIN{RS=“x”}{print}’ p.txt ##碰到x就换行
awk ‘BEGIN{ORS="------"}{print}’ p.txt ##以“------”连接内容
还可以做逻辑判断
awk ‘NR>3 && NR<10{print NR,$0}’ p.txt ##打印4-9行一整行内容,并打印出行号
awk ‘NR<10 || NR>20{print NR,$0}’ p.txt ## 打印1-9行或者大于20行的
seq 100 | awk ‘$1~/7/{print $1}’ ##打印出1-100内包含7的数
seq 100 | awk ‘$1~/7/ && $1%7==0 {print $1}’ ## 打印出1-100内包含7的数并且可以被7整除的数
3.3、awk内的if语句
固定格式
单分支为if() {}
双分支为if(){}else{}
多分支为if(){}else if(){}else{}
实例
awk -F: ‘{if($3>1000){print $3}}’ /etc/passwd
awk -F: ‘{if($3>1000){print $0}else{print $1}}’ /etc/passwd ##第三列大于1000,打印整行,否则打印第一列
4、结合特殊符号-“~ ” 、“!~”
~ ##模糊匹配;非精确匹配
!~ ##非
实例:
awk -F: ‘/sbin/{print NR,$0}’ p.txt
awk -F: ‘$1~/mail/{print $NF}’ p.txt ##匹配第一列是mail,并输出最后一列
awk -F: ‘NR~/3/{print NR,$0}’ /etc/shadow ##打印shadow文件内包含3的内容
awk -F: ‘KaTeX parse error: Expected '}', got 'EOF' at end of input: …/dae/{print NR,NF}’ yy.txt ##打印不是dea开头的第五列,并显示行号
awk -F: ‘$2~/!/{print NR,$1}’ /etc/shadow ##输出shadow文件中以冒号分隔的第二列有感叹号的行的内容
5、精确匹配-“=”、“>=”、“字符串”
==:等于;精确匹配
>=:大于等于;精确匹配
“字符串”:精准匹配一个字符串,需要双引号
实例
awk -F: ‘NR1{print $0}’ p.txt ##打印出第一整行内容
awk -F: ‘NR>=33{print NR,$0}’ /etc/shadow ##精确匹配大于等于33行并输出内容
awk -F: '$1"ntp"{print NR,$0}’ /etc/shadow ##打印ntp开头的那一行,并显示行号
awk -F:: ‘NR1{print NF,$0}’ /etc/shadow ##打印出第一行,并以::分隔显示列数
ifconfig ens33 | awk ‘/netmask/{print “ip:”$2}’ ##精确输出本机ip地址
df -h | awk 'NR2{print"avil:"$4}’ ## 打印第二行第四列
free -m | awk ‘NR2{print"free:"$4}’ ##打印第二行第四列
free -m | awk 'NR2{print"free:"$3}’ ##打印第二行第三列
free -m | awk ‘NR==3{print"free:"$3}’ ##打印第三行第三列
以上是关于shell编程-正则表达式与文本处理器sedawk的主要内容,如果未能解决你的问题,请参考以下文章