Linux三剑客grep、sed、awk
一、grep
Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。
grep是“全局正则表达式打印”的缩写(global regular expression print)
1、查看grep帮助
grep --help
2、语法
grep [选项] ‘搜索模式’ 文件
'搜索模式':可以是普通文本或正则表达式
文件:要查找的目标文件,可以是多个;若不指定则默认从标准输入读取
3、主要参数
[选项]主要参数:
-c:仅显示匹配的行数
-i:不区分大小写(只适用于单字符)
-l:只列出匹配的文件名
-n:显示匹配行及行号
-r 或 -R:递归搜索目录
-v:反向匹配(显示不匹配的行)
-o:仅输出匹配的部分
-E:使用扩展正则表达式(相当于使用 egrep)
pattern正则表达式主要参数:
^:匹配正则表达式的开始行
$: 匹配正则表达式的结束行
.:匹配所有单个字符(不包括换行符)
*:前导字符,出现0次或多次
?:前导字符,出现0次或1次(扩展正则)
+:前导字符,出现1次或多次(扩展正则)
\:用于转义特殊字符,使得其失去特殊意义而成为普通字符
\<:从匹配正则表达式的行开始
\>:到匹配正则表达式的行结束
[ ]:单个字符,如[A]即A符合要求
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求
[^] :匹配一个不在指定范围内的字符
{n}:匹配确定的n次(扩展正则)
{n,}:至少匹配n次(扩展正则)
{n,m}:前导字符出现最小n次,最多m次(扩展正则)
|:逻辑或,用于表示两个或多个模式之间的选择(扩展正则)
():分组,圆括号内的内容被视为一个整体,可作为后续量词的作用对象,也可用于捕获子表达式进行替换或引用(扩展正则)
预定义字符:
\d:匹配一个数字字符,相当于 [0-9]
\D:匹配一个非数字字符,相当于 [^0-9]
\s:匹配一个空白字符,包括空格、制表符、换页符等等
\S:匹配一个非空白字符
\w:匹配字母、数字及下划线,相当于 [A-Za-z0-9_]
\W:匹配非字母、非数字、非下划线字符[^A-Za-z0-9_]
4、语法练习
(1)在 /etc/passwd 文件中查找包含 ftp 的行
grep ftp /etc/passwd
(2)在 /etc/passwd 文件中查找包含 ftp 的行,并显示行号
grep -n ftp /etc/passwd
(3)显示匹配行(ftp)及其前 2 行
grep -n -B 2 ftp /etc/passwd
(4)显示匹配行(ftp)及其后 2 行
grep -n -A 2 ftp /etc/passwd
(5)显示匹配行(ftp)及其前后各 2 行
grep -n -C 2 ftp /etc/passwd
(6)在 /etc/passwd 文件中不区分大小写地查找包含"ftp"的行
grep -i ftp /etc/passwd
(7)查找 /etc/passwd 文件中以 "root" 开头的行
grep ^root /etc/passwd
(8)查找 /etc/passwd 文件中以 "bash" 结尾 的行
grep bash$ /etc/passwd
(9)在 /etc/passwd 文件中查找匹配正则表达式 o 的行
? 匹配前面的字符(o)0次或1次
egrep o? /etc/passwd
或
grep -E o? /etc/passwd
* 匹配前一个字符(o)0次或多次
grep o* /etc/passwd
+ 匹配前导字符(o)1次或多次
egrep o+ /etc/passwd
或
grep -E o+ /etc/passwd
(10)[]使用案例
匹配任意单个大写字母(从A到Z)
grep [A-Z] /etc/passwd
匹配单个字符,该字符可以是:大写字母 A、逗号、大写字母 Z
grep [A,Z] /etc/passwd
^ 在方括号内表示否定匹配,匹配任意单个字符,只要该字符不是大写字母 S
grep [^S] /etc/passwd
查找不以字母 S 或符号 ^ 开头的行
grep ^[^S^] /etc/passwd
(11)输出 /etc/passwd 文件中 所有非空行
grep . /etc/passwd
(12)在 /etc/passwd 文件中查找 包含连续两个字母 o 的行
o{2} 表示:精确匹配连续 2个字母 o(即 oo)
egrep o{2} /etc/passwd
或
grep -E o{2} /etc/passwd
(13)在 /etc/passwd 文件中查找包含字母 a 后接任意字符(包括零个字符),最后以字母 b 结尾的子串的行
grep 'a.*b' /etc/passwd
(14)从 /etc/passwd 文件中提取所有包含 : 的行,并只显示每行中 第一个冒号(:)之前的内容,即用户名部分
grep '^[^:]*:' /etc/passwd
或
grep '^\w*:' /etc/passwd
(15)在 /etc/passwd 文件中搜索包含 "root" 或 "ftp" 的行
grep 'root\|ftp' /etc/passwd
二、sed
sed(stream editor)是 Linux 中强大的文本处理工具之一,用于以流的方式对文本进行处理。它可以执行替换、删除、插入、新增等操作,常用于批量文本编辑、自动化脚本、日志处理等场景。
sed 的优势:
- 不需要打开编辑器即可快速修改文件内容
- 可与 shell 脚本或管道命令结合,实现复杂文本处理逻辑
- 支持正则表达式,功能灵活强大
1、查看sed帮助
sed --help:只能查看简单参数
man sed:查看man手册获取帮助
2、语法
sed [选项] '命令' 文件名
3、常用参数
-n:禁止默认输出,只打印处理过的行
-i:直接修改文件内容(慎用)
-e:允许多个编辑命令
-r:使用扩展正则表达式
常用动作命令:
s/原字符串/新字符串/:替换
d:删除
p:打印
a:追加
i:插入
c:替换整行
y/source/dest/:字符转换(将一组字符逐个替换为另一组对应的字符)
r filename:读取文件并插入内容
w filename:写入到指定文件
4、语法练习
(1)删除 /etc/passwd 文件的第 30 行,但 不会修改原文件,而是将结果输出到标准输出(屏幕)
sed '30d' /etc/passwd
(2)在 /etc/passwd 文件中查找 ftp 并替换为 abc,但只替换每行第一次匹配到的 ftp
sed 's/ftp/abc/' /etc/passwd
(3)p动作命令使用案例
- number
仅打印 /etc/passwd 文件中包含 ftp 的行,而忽略其他内容
sed -n '/ftp/p' /etc/passwd
仅打印 /etc/passwd 文件的第 5 行
sed -n '5p' /etc/passwd
- first~step
从第 2 行开始,每隔 2 行打印一次(即打印所有偶数行)
sed -n '2~2p' /etc/passwd
第一个 2 表示 起始行号(从第 2 行开始)
~2 表示 步长(每隔 2 行取一次)
从第 1 行开始,每隔 2 行打印一次(即打印所有奇数行)
sed -n '1~2p' /etc/passwd
从第5行开始,每隔3行打印一次内容
sed -n '5~3p' /etc/passwd
5:起始行号(从第5行开始)
~3:步长(每隔3行选取一次)
- $
在 /etc/passwd 文件中查找 以 "shutdown" 结尾的行 并打印出来
sed -n '/shutdown$/p' /etc/passwd
- addr1,addr2
打印 /etc/passwd 文件的前 3 行
sed -n '1,3p' /etc/passwd
显示文件从第10行到末尾的所有内容
sed -n '10,$p' /etc/passwd
- addr1,+N
从第5行开始,打印该行及随后的3行(共打印4行内容)
sed -n '5,+3p' /etc/passwd
(4)d动作命令使用案例
删除 /etc/passwd 文件的第一行
sed '1d' /etc/passwd
删除文件中的奇数行
sed '1~2d' /etc/passwd
1~2:从第1行开始,每隔2行选择一次(即所有奇数行:1,3,5,...)
删除文件的最后一行
sed '$d' /etc/passwd
删除文件从第5行到末尾的所有内容
sed '5,$d' /etc/passwd
删除匹配行及其后两行
sed '/^ftp/,+2d' /etc/passwd
(5)s///动作命令使用案例
将 /etc/passwd 中所有以 nologin 结尾的登录 shell 替换为 bash
sed 's/nologin$/bash/' /etc/passwd
sed 's#nologin$#bash#' /etc/passwd
sed 's!nologin$!bash!' /etc/passwd
将 /etc/passwd 中所有 /sbin 路径替换为 /bin
sed 's/\/sbin/\/bin/' /etc/passwd
在 /etc/passwd 文件中全局替换所有出现的 ftp 为 abc
sed 's/ftp/abc/g' /etc/passwd
在/etc/passwd 文件中从第5行开始到文件末尾,将所有 nologin 替换为 bash
sed '5,$s/nologin/bash/g' /etc/passwd
在/etc/passwd 文件中仅修改以 daemon: 开头的行中的 nologin 为 bash
sed '/^daemon:/s/nologin/bash/g' /etc/passwd
(6)a动作命令使用案例
在/etc/passwd 文件中的每一行后面追加新行 "hello"
sed 'a hello' /etc/passwd
在 /etc/passwd 文件的第 1 行之后追加新行 "hello"
sed '1a hello' /etc/passwd
在 /etc/passwd 文件的最后一行之后追加新行 "hello"
sed '$a hello' /etc/passwd
在 /etc/passwd 文件中从第 5 行到末尾的每一行后追加新行"hello"
sed '5,$a hello' /etc/passwd
在 /etc/passwd 文件第一行后追加多行文本“hello”“world”
sed -e '1a hello' -e '1a world' /etc/passwd
在 /etc/passwd 文件第一行之后追加多行文本
sed -e '1a hello\nworld' /etc/passwd
hello\nworld:要插入的两行文本(\n 是换行符)
(7)i动作命令使用案例
在 /etc/passwd 文件第一行之前插入多行文本
sed -e '1i hello\nworld' /etc/passwd
在 /etc/passwd 文件最后一行之前插入内容
sed -e '$i hello' /etc/passwd
(8)c动作命令使用案例
将/etc/passwd整个文件内容替换为 hello
sed 'c hello' /etc/passwd
将/etc/passwd文件中以 adm: 开头的行替换为“hello”
sed '/^adm:/c hello' /etc/passwd
将/etc/passwd文件中第3行到第7行的所有内容替换为单行“hello”
sed '3,7c hello' /etc/passwd
(9)(y/source/dest/)动作命令使用案例
将/etc/passwd文件中的字符 a、b、c 分别替换为 1、2、3
sed 'y/abc/123/' /etc/passwd
(10)(r filename)动作命令使用案例
在 /etc/passwd 文件的每行后插入 /etc/group 的全部内容
sed 'r /etc/group' /etc/passwd
在 /etc/passwd 文件的末尾插入 /etc/group 的全部内容
sed '$r /etc/group' /etc/passwd
(11)(w filename)动作命令使用案例
将 /etc/passwd 的内容写入到指定文件/root/test中
sed 'w /root/test' /etc/passwd
查看test文件验证
cat test
三、awk
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
AWK 通过提供编程语言的功能,如变量、数学运算、字符串处理等,使得对文本文件的分析和操作变得非常灵活和高效。
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger 和 Brian Kernighan 的 Family Name 的首字符。
AWK最原始的版本是1977年在AT&T贝尔实验室诞生的,AWK经过改进生成的新的版本nawk,gawk,现在默认linux系统下日常使用的是gawk。
1、查看awk帮助
awk --help
man awk
2、语法
awk options 'pattern {action}' file
选项参数说明:
options:是一些选项,用于控制 awk 的行为。
pattern:是用于匹配输入数据的模式。如果省略,则 awk 将对所有行进行操作。
{action}:是在匹配到模式的行上执行的动作。如果省略,则默认动作是打印整行。
3、常用参数
选项参数
-F:指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F: (--field-separator)
内置变量
FS:字段分隔符(默认是任何空格)
$n:指定分隔的第n个字段,如$1、$3分别表示第1、第3列
$0:代表输入整行内容
NF:number of fields,当前行的字段数
NR :表示 当前行号(Number of Record,从1开始)
数学函数
int(x):取整数部分
rand():⽣成0到1之间的浮点数(包含 0,但不包含 1)
字符串函数
length([s]):返回字符串⻓度
tolower(s):转换为⼩写
toupper(s):转换为⼤写
时间函数
systime():返回当前时间戳(秒数)
4、语法练习
(1)print、$练习案例
打印 /etc/passwd 文件的全部内容
awk '{print}' /etc/passwd
或
awk '{print $0}' /etc/passwd
(2)//匹配代码块案例练习
在 /etc/passwd 文件中查找以 root 开头的行,如果找到则打印字符串 "world"
awk '/^root/{print "world"}' /etc/passwd
(3)设置字段分隔符为 : 打印/etc/passwd 文件每行的第一个字段
awk -F: '{print $1}' /etc/passwd
或
awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
(4)结合 预处理、逐行处理 和 后处理
awk 'BEGIN{print "hello"}{print "test"}END{print "world"}' /etc/passwd
BEGIN 块:初始化操作(本例打印 hello)
主处理块 {print "test"}:处理每行内容(本例忽略行内容,固定打印 test)
END 块:汇总结果(本例打印字符串 world)
(5)内置变量练习案例
打印 /etc/passwd 文件中每一行的字段数量
awk -F: '{print NF}' /etc/passwd
打印 /etc/passwd 文件中每一行的行号
awk -F: '{print NR}' /etc/passwd
提取 /etc/passwd 文件中每一行的最后一个字段
awk -F: '{print $NF}' /etc/passwd
提取 /etc/passwd 文件中每一行的倒数第二个字段
awk -F: '{print $(NF-1)}' /etc/passwd
(6)条件表达式(== 、!=、>、>=)案例练习
提取 /etc/passwd 文件中第 5 行的最后一个字段(即第 5 个用户的默认 Shell)
awk -F: 'NR==5{print $NF}' /etc/passwd
从 /etc/passwd 文件的第 6 行开始(跳过前5行),打印每一行的完整内容
awk -F: 'NR>5{print $0}' /etc/passwd
从 /etc/passwd 文件中 GID(组ID,第4列)大于3的所有行,打印完整行内容
awk -F: '$4>3{print $0}' /etc/passwd
(7)逻辑运算符(&&、||)案例练习
打印 /etc/passwd 文件中第5行和第7行的完整内容
awk -F: 'NR==5 || NR==7{print $0}' /etc/passwd
打印 /etc/passwd 文件中第5行到第7行(共3行)的完整内容
awk -F: 'NR>=5 && NR<=7{print $0}' /etc/passwd
(8)数值运算案例练习
从 /etc/passwd 文件中筛选出 GID(组ID,第4列)大于10的行,并打印该GID乘以2的结果
awk -F: '$4>10{print $4*2}' /etc/passwd
从 /etc/passwd 文件中筛选出 GID(组ID,第4列)大于10的行,并计算并打印 GID - 10 的结果
awk -F: '$4>10{print $4-10}' /etc/passwd
从 /etc/passwd 文件中筛选出 GID(组ID,第4列)大于10的行,并计算并打印 GID / 3 的结果
awk -F: '$4>10{print $4/3}' /etc/passwd
从 /etc/passwd 文件中筛选出 GID(组ID,第4列)大于10的行,计算 GID / 3 并取整,然后打印结果
awk -F: '$4>10{print int($4/3)}' /etc/passwd
为 /etc/passwd 文件的每一行生成一个随机数(0到1之间的浮点数)并打印
awk '{print rand()}' /etc/passwd
统计 /etc/passwd 文件的总行数,并在处理完所有行后打印结果
awk 'END{print NR}' /etc/passwd
为 /etc/passwd 文件中的每个用户(第1列)生成一个随机数(0到1之间),并格式化输出为 用户名 分配 随机数 的形式
awk -F: '{print $1,"分配",rand()}' /etc/passwd
rand() 生成 [0, 1) 区间的浮点数(包含 0,但不包含 1)
为 /etc/passwd 文件中的每个用户(第1列)生成一个 1~30 的随机整数,并格式化输出为 用户名 分配 随机数 的形式
awk -F: '{print $1,"分配",int(rand()*30)+1}' /etc/passwd
rand() * 30 → 范围是 [0, 30)(包含 0,但不包含 30)
int() 取整 → 范围是 [0, 29](因为 int(29.999...) = 29)
+1 后 → 最终范围是 [1, 30]
(9)字符串函数案例练习
将 /etc/passwd 文件中每一行的第一个字段(用户名)转换为大写字母,并打印结果
awk -F: '{print toupper($1)}' /etc/passwd
将 /etc/passwd 文件中每一行的第一个字段(用户名)转换为小写字母,并打印结果
awk -F: '{print tolower($1)}' /etc/passwd
计算 /etc/passwd 文件中每个用户名(第1列)的长度(字符数),并打印结果
awk -F: '{print length($1)}' /etc/passwd
筛选并打印 /etc/passwd 文件中用户名(第1列)长度超过10个字符的行
awk -F: 'length($1)>10{print $0}' /etc/passwd
(10)时间函数案例练习
将 /etc/passwd 文件中每一行的用户名(第1列)转换为小写,并附加当前的时间戳(Unix 时间戳,秒级)
awk -F: '{print tolower($1),systime()}' /etc/passwd
(11)数值统计案例练习
计算 /etc/passwd 文件中所有用户的 UID(第3列)的总和,并在最后打印结果
awk -F: 'BEGIN{sum=0}{sum=sum+$3}END{print sum}' /etc/passwd
计算 /etc/passwd 文件中所有用户的 UID(第3列)的平均值,并在最后打印结果
awk -F: 'BEGIN{sum=0}{sum=sum+$3}END{print sum/NR}' /etc/passwd
(12)控制语句案例练习
条件语句(if-else)
打印 /etc/passwd 文件中 UID(用户ID)大于 1000 的所有用户行
awk -F: '{if ($3>1000) print $0}' /etc/passwd
处理 /etc/passwd 文件,根据 UID(第3列)的值进行条件判断并输出,如果 UID 大于 1000,则打印整行内容($0);否则,仅打印用户名(第1列,$1)
awk -F: '{if ($3>1000) print $0; else print $1}' /etc/passwd
循环语句
a. while 循环
对 /etc/passwd 文件中的每一行,循环打印用户名(第1列)3次
awk -F: '{i=1; while (i<=3) {print $1; i++}}' /etc/passwd
b. for 循环
遍历 /etc/passwd 文件的每一行,打印每行的前 4 个字段(列)并标注字段位置
awk -F: '{for(i=1; i<=4; i++) print "字段" i ": " $i}' /etc/passwd
遍历 /etc/passwd 文件的每一行,打印前 4 个字段(列),但跳过第 2 个字段(密码占位符 x)
awk -F: '{for(i=1; i<=4; i++) {if (i == 2) continue; print "字段" i ": " $i}}' /etc/passwd
遍历 /etc/passwd 文件每行的前 4 个字段,但当处理到第 2 个字段时立即终止循环,因此实际只会打印第 1 个字段
awk -F: '{for(i=1; i<=4; i++) {if(i == 2) break; print "字段" i ": " $i;}}' /etc/passwd