文本三剑客grep,sed,awk
1、Linux核心通配符
1.1 正则表达式
常用通配符:
- *:匹配任意长度的任意字符
- ?或.:匹配任意单个字符
- []:匹配指定范围内的任意单个字符
- [^]:匹配指定范围外的任意单个字符
匹配次数:
- *:匹配前面的字符任意次
- .*:匹配任意长度的任意字符
- ?:匹配器前面的字符0次或1次
- +:匹配前面的字符1次或多次;即前面的字符要出现至少1次
- \ {m \}: 匹配其前面的字符m次
- \ {m ,n \}:匹配其前面的字符至少m次,至多n次
- \ {0,n \}:至多n次
- \ {m , \}:至少m次
位置锚定:
- ^: 行首锚定;用于模式最左侧
- $: 行尾锚定;用于模式最右侧
- ^$: 空白行
- \< 或\b: 词首锚定
- \>或\b: 词尾锚定
分组及引用:
- \(\): 将一个或者多个捆绑在一起,当作一个整体。
- \(\)ab\1: 第一个左括号与之匹配的右括号之间的模式所匹配到的字符。
- \(\)ab\2:第二个左括号与之匹配的右括号之间的模式所匹配到的字符。
1.2 扩展正则表达式
字符匹配:
- . : 匹配任意单个字符
- []:匹配指定范围内的任意单个字符
- [^]:匹配指定范围外的任意单个字符
匹配次数:
- *: 任意次数
- ?:0次或1次
- +: 其前面的字符至少出现一次
- {m}: 其前面的字符出现m次
- {m,n}:至少m次,至多n次
- {0,n}:至多n次
2、Linux文本处理三剑客之grep
grep是一个文本搜索工具,根据用户指定的模式(过滤条件),对文本逐行进行匹配检查;打印匹配到的行。
模式:有正则表达式的元字符及文本字符所编写的过滤条件。
grep [OPTIONS] PATTERN [FILE...]
常用选项:
- -i:忽略字符的大小写
- -o:仅显示匹配到的字符串本身
- -v:显示不能被匹配到的行
- -E:支持使用扩展的正则表达式元字符
- -q:静默模式,既不输出任何信息
grep -v "bin/bash$" /etc/passwd #显示/etc/passwd文件中不以/bin/bash结尾的行。
grep "\<[0-9]\{2,3\}\>" /etc/passwd #找出/etc/passwd文件中的两位数或三位数。
grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg #找出文件/etc/grub2.cfg中,以至少一个空白字符开头,且后面是非空白字符的行。
grep -i "^s" /proc/meminfo #找出文件/proc/meminfo中,所有以大写或小写s开头的行,其还有以下两种方式。
grep "^[Ss]" /proc/meminfo
grep -E "^(s|S)" /proc/meminfo
grep -E "^(root|centos|user1)\>" /etc/passwd #显示当前系统上root,centos,user1用户的相关信息。
示例:取自己本机IP
[root@master ~]# ifconfig ens33 | grep -Eo 'inet(.*)netmask' | grep -Eo '([0-9]{1,3}.){1,3}[0-9]{1,3}'
192.168.248.144
3、Linux文本三剑客之sed
sed是一种新型的,非交互式的编辑器
sed编辑器逐行处理文件,并将结果输出到屏幕。sed把当前正在处理的行保存在一个临时缓存区中,这个缓存区称为模式空间或临时缓冲。sed把每一行都存在模式空间里,对这个副本进行编辑。所以不会修改或者破坏源文件。
常用选项:
- -n:不输出模式空间中的内容屏幕
- -e:多单编辑
- -f:每一行一个编辑命令
- -r:支持使用扩展正则表达式
- -i:直接编辑原文
编辑命令:
- d:删除
- p:显示模式空间中的内容
- a \text:在行后面追加文本text,支持使用\n实现多行追加
- i \text:在行后面插入文本text,支持使用\n实现多行追加
- c \text:把匹配到的行替换为此处指定的文本text
- !:条件取反
- s///:查找替换,其分隔符可自行指定,常用的有s@@@,s###等;
- g:全局替换
- w /PATH/TO/SOMEFILE:将替换成功的结果保存至文件中
- p:显示替换成功的行
3.1 打印模式空间(命令 p)
1、它打印出/etc/passwd 文件中的所有行
sed -n 'p' /etc/passwd
2、也可以使用 –e 选项,执行多个 sed 命令
sed [ options ] –e {sed-command-1} –e {sed-command-2} {input-file}
如果使用-e 执行多个命令,也可以使用反斜杠\把它们分割到多行执行
sed –n –e ‘/^root/ p’ –e ‘/^nobody/ p’ /etc/passwd
#打印/etc/passwd 中以 root 和 nobody 开头的行
Sed –n \
-e '/^root/ p' \
-e '/^nobody/ p' \
/etc/passwd
3、命令 p 可以控制只输出你指定的内容。通常使用 p 时,还需要使用-n 选项来 屏蔽 sed 的默认输出,否则当执行命令 p 时,每行记录会输出两次。
[root@k8s-master ~]# sed 'p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sed -n 'p' /etc/passwd #加-n
[root@k8s-master ~]# sed -n 'p' /etc/passwd
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
3.2指定地址范围
sed -n '2 p' employee.txt #只打印第 2 行
sed -n '1,4 p' employee.txt #打印第 1 至第 4 行
sed -n '2,$ p' employee.txt #打印第 2 行至最后一行($代表最后一行)
sed -n '1~2 p' employee.txt #只打印奇数行
模式匹配
sed -n '/Jane/ p' employee.txt #打印匹配模式”Jane”的行
sed -n '/Jason/,4 p' employee.txt #打印第一次匹配 Jason 的行至第 4 行的内容。如果开始的 4 行中,没有匹配到 Jason,那么 sed 会打印第 4 行以后匹配到 Jason 的内容。
sed -n '/Raj/,$ p' employee.txt #打印从第一次匹配 Raj 的行到最后的所有行。
sed -n '/Raj/,/Jane/ p' employee.txt #打印自匹配 Raj 的行开始到匹配 Jane 的行之间的所有内容。
sed -n '/Jane/,+2 p' employee.txt #打印匹配 Jason 的行和其后面的两行。
3.3删除行
sed '2 d' employee.txt #只删除第 2 行
sed '1,4 d' employee.txt #删除第 1 至第 4 行。
sed '1~2 d' employee.txt #只删除奇数行
sed '/Manager/ d' employee.txt #删除匹配 Manager 的行
sed '/Raj/,$ d' employee.txt #删除从第一次匹配 Raj 的行至最后一行。
sed '/Jason/,+2 d' employee.txt #删除第一次匹配 Jason 的行和紧跟着它后面的两行。
sed ‘/^$/ d’ employee.txt #删除所有空行
sed ‘/^#/ ‘ employee.txt #删除所有注释行(假定注释行以#开头)
3.4 把模式空间内容写到文件中(w 命令)
sed -n 'w output.txt' employee.txt #把 employee.txt 的内容保存到文件 output.txt,但不在屏幕上显示。
sed -n '2 w output.txt' employee.txt #只保存第2行。
sed -n '1,4 w output.txt' employee.txt #保存第1至第4行。
sed -n '2,$ w output.txt' employee.txt #保存第 2 行起至最后一行。
sed -n '1~2 w output.txt' employee.txt #只保存奇数行
sed -n '/Raj/,/Jane/ w output.txt' employee.txt #保存匹配 Raj 的行至匹配 Jane 的行。
sed -n '/Jason/,+2 w output.txt' employee.txt #保存匹配 Jason 的行以及紧跟在其后面的两行。
3.5 sed替换命令
sed 's/Manager/Director/' employee.txt #用 Director 替换所有行中的 Manager。
sed '/Sales/s/Manager/Director/' employee.txt #sed '/Sales/s/Manager/Director/' employee.txt.
sed 's/a/A/g' employee.txt #把所有小写字母 a 替换为大写字母 A。
sed 's/a/A/2' employee.txt #把第二次出现的小写字母 a 替换为大写字母 A。
sed -n 's/John/Johnny/p' employee.txt #后面加p。打印替换后的行。
sed -n 's/John/Johnny/w output.txt' employee.txt #把替换后的行写入output.txt文件中
3.6 分组替换
sed -r 's/([^,]*).*/\1/g' employee.txt #([^,]*)匹配字符串从开头到第一个逗号之间的所有字符(并将其放入第一个分组中),\1将第一个分组输出。
sed -r 's/^([^,]*),([^,]*),([^,]*)/\1,\3/' employee.txt #在这个例子中,划分了三组,以逗号隔开。
#注释:每一个括号为一个分组,括号之间的逗号为分隔符,\1,\3为第一组,第三组内容,将其输出。
同时因为可以交换输出
[root@master ~]# sed -r 's/^([^,]*),([^,]*),([^,]*)/\2,\1,\3/' employee.txt #先输出第二组,在输出一,三组。
John Doe,101,CEO
Jason Smith,102,IT Manager
Raj Reddy,103,Sysadmin
Anand Ram,104,Developer
Jane Miller,105,Sales Manager
3.7实例:获取本机IP:
[root@master ~]# ifconfig ens33 | sed -rn 's/inet(.*)netmask(.*)/\1/p'|sed 's/[[:space:]]//g'
192.168.248.144 #其第一个括号内的内容为第一个分组,第二个括号为第二个分组,后面的/\1/p内容,是将第一个分组的内容输出。
3.8 sed使用正则表达式
sed -n '/^103/ p' employee.txt #显示以 103 开头的行
sed -n '/r$/ p' employee.txt #显示以字符 r 结尾的行
sed -n 's/J... /Jason /p' employee.txt #“J… ”同时匹配 employee.txt 文件中的“John”和“Jane”
sed -n '/[234]/ p' employee.txt #匹配包含 2、3 或者 4 的行,也可以 sed -n '/[2-4]/ p' employee.txt
sed -n '/101\|102/ p' employee.txt #打印包含 101 或者包含 102 的行
sed -n '/[0-9]/ p' employee.txt #打印包含任意数字的行
字符边界\b
\b 用来匹配单词开头(\bxx)或结尾(xx\b)的任意字符,因此\bthe\b 将匹配 the,但不匹配 they. \bthe 将匹配 the 或 they。
sed -n '/\bJohn\b/ p' employee.txt #匹配包含整个单词John所在的行。
3.9 sed附加命令
3.9.1 追加命令(命令 a)
sed '$ a 106,Jack Johnson,Engineer' employee.txt #在 employee.txt 文件结尾追加一行。
sed '/Jason/a\203,Jack Johnson,Engineer\n204,Mark Smith,Sales Engineer' employee.txt #在匹配 Jason 的行的后面追加两行。
3.9.2插入命令(命令 i)
sed '2 i 203,Jack Johnson,Engineer' employee.txt #在 employee.txt 的第 2 行之前插入一行
sed '/Jason/i\203,Jack Johnson,Engineer\n204,Mark Smith,Sales Engineer' employee.txt #在匹配 Jason 的行的前面插入两行
3.9.3 修改命令(命令 c)
sed '2 c 202,Jack,Johnson,Engineer' employee.txt #用新数据取代第 2 行
3.9.4 打印行号(命令=)
sed '/Jane/ =' employee.txt #打印包含关键字”Jane”的行的行号,同时打印输入文件中的内容
3.9.5 转换字符(命令 y)
sed 'y/abcde/ABCDE/' employee.txt #将把 a 换为 A,b 换为 B,c 换为 C,以此类推
4.Liunx文本处理三剑客之awk
awk是一种编辑语言,用于对文本和数据进行处理。出书可以来自标准输入,一个或多个文件,或其他命令的输出。它支持用户自定义函数和动态正则表达式等先进功能。
awk对文件逐行扫描,寻找匹配的特定模式的行,对其进行操作。
4.1 Awk 程序结构(BEGIN,body,END)区域
4.1.1 BEGIN 区域
BEGIN 区域的命令只最开始、在 awk 执行 body 区域命令之前执行一次。
- BEGIN 区域很适合用来打印报文头部信息,以及用来初始化变量。
- BEGIN 区域可以有一个或多个 awk 命令
- 关键字 BEGIN 必须要用大写。
- BEGIN 区域是可选的。
4.1.2 body 区域
body 区域的命令每次从输入文件读取一行就会执行一次.
- 如果输入文件有 10 行,那 body 区域的命令就会执行 10 次(每行执行一次)。
- Body 区域没有用任何关键字表示,只有用正则模式和命令。
4.1.3 END block
END 区域在 awk 执行完所有操作后执行,并且只执行一次。
- END 区域很适合打印报文结尾信息,以及做一些清理动作。
- END 区域可以有一个或多个 awk 命令。
- 关键字 END 必须要用大写。
- END 区域是可选的。
4.2 awk选项含义
- -f:从指定文件读取awk程序源。
- -F:使用指定文件系统为输入字段分隔符
4.3 内置变量
- FILENAME:当前输入文件的名称。
- FNR:当前输入文件的输入记录数
- FS:输入字段分隔符,默认为一个空格
- NF:在当前输入记录中的字段的数目
- NR:已读的记录数
- OFS:输出字段分隔符。
- ORS:输出记录分隔符
- RS:输入记录分隔符,默认为一个换行符
- DFMT:用于数字的输出格式
- RT:记录终止符
- RSTART:匹配第一个字符的索引
- RLENGTH:匹配字符串长度
4.4 举例
NR举例
awk -F: '{print NR, $0}' /etc/passwd /etc/hosts
FNR举例
awk -F: '{print FNR, $0}' /etc/passwd /etc/hosts
FS举例
awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd
awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd
FILENAME举例
awk -F: '{print FILENAME, $0}' /etc/passwd /etc/hosts
RS举例
awk -F, 'BEGIN{RS=","} {print $0}' employee.txt #以逗号为换行符。
运用正则举例
awk -F ',' '/Manager/ {print $2,$3}' employee.txt #输出Manager所在的行并以逗号分隔,输出第二,第三列。
[root@master ~]# awk -F ',' '/Manager/ {print $2,$3}' employee.txt
Jason Smith IT Manager
Jane Miller Sales Manager
[root@master ~]# awk -F ',' '/^102/{print "Emp id 102 is",$2}' employee.txt #搜索以102开头的行,并在第二列前面加字符串Emp id 102 is输出。
Emp id 102 is Jason Smith
OFS举例
[root@master ~]# awk -F ',' 'BEGIN {OFS=":"} {print $2,$3}' employee.txt #以逗号分隔,以冒号作为输出分隔符。输出第二列,第三列。
John Doe:CEO
Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
Jane Miller:Sales Manager
NR举例
NR 非常有用,在循环内部标识记录序号。用于 END 区域时,代表输入文件的总记录数。
awk 'BEGIN {FS=","} {print "Emp Id of record number",NR,"is",$1;} END {print "Total number of records:",NR}' employee.txt
4.5 一元操作符
只接受单个操作数的操作符叫做一元操作符。
- +:取正
- -:取反
- ++:自增
- –:自减
[root@master ~]# awk -F, '{print -$4}' employee-sal.txt
-10000
-5000
-4500
-4500
-3000
自增:
[root@master ~]# awk -F, '{print ++$4}' employee-sal.txt
10001
5001
4501
4501
3001
自减:
[root@master ~]# awk -F, '{print --$4}' employee-sal.txt
9999
4999
4499
4499
2999
4.6 负值操作符
与其他大部分编程语言一样,awk 使用 = 作为赋值操作符。和 C 语言一样,awk 支持赋值 的缩写方式。
- =:负值
- +=:加法负值
- -=:减法负值
- *=:乘法负值
- /=:除法负值
- %/:取模负值
awk -F ',' 'BEGIN { total=0 } { total += $4 } END {print "Total Quantity: " total }' employee-sal.txt #设置变量total等于0,以逗号分隔,使total等于第四列相加,然后加字符输出。
awk -F ',' 'BEGIN { total = 0 } { total += NF } END { print total }' employee-sal.txt #以逗号分隔,total等于字符的总数量。
4.7 比较操作符
- >:大于
- <:小于
- ==: 等于
- !=:不等于
- &&:且
- ||:或
- >=:大于等于
- <=:小于等于
awk -F ',' '$5 <= 5' items.txt #打印数量小于等于临界值 5 的
awk -F "," '$1 == 103' items.txt #打印编号为 103 的
awk -F "," '$3 != "Video"' items.txt #打印除 Video 以外的
awk -F "," '$4 < 900 && $5 <= 5' items.txt #使用&&比较两个条件,打印价钱低于 900 并且数量小于等于临界值 5。
awk -F "," '$4 < 900 || $5 <= 5' items.txt #使用||比较两个条件,打印价钱低于 900 或者数量小于等于临界值 5 的
实例:打印/etc/password 中最大的 UID(以及其所在的整行)。Awk 把最大的 UID(第 3 个字段)放在变量 maxuid 中,并且把包含最大 UID 的行复制到变量 maxline 中。循 环执行完后,打印最大的 UID 和其所在的行。
[root@master ~]# awk -F ':' '$3 > maxuid { maxuid = $3; maxline = $0 } END { print maxuid,maxline }' /etc/passwd
1000 elsearch:x:1000:1000::/home/elsearch:/bin/bash
aming\Typora\typora-user-images\image-20230402150418428.png" alt=“image-20230402150418428” style=“zoom:80%;” />
awk -F "," '$4 < 900 || $5 <= 5' items.txt #使用||比较两个条件,打印价钱低于 900 或者数量小于等于临界值 5 的
实例:打印/etc/password 中最大的 UID(以及其所在的整行)。Awk 把最大的 UID(第 3 个字段)放在变量 maxuid 中,并且把包含最大 UID 的行复制到变量 maxline 中。循 环执行完后,打印最大的 UID 和其所在的行。
[root@master ~]# awk -F ':' '$3 > maxuid { maxuid = $3; maxline = $0 } END { print maxuid,maxline }' /etc/passwd
1000 elsearch:x:1000:1000::/home/elsearch:/bin/bash