前言
在Linux文本处理领域,grep、sed、awk凭借各自独特的优势被尊称为“Linux三剑客”:grep专注于模式搜索,能快速定位文本;sed擅长文本编辑,可灵活处理内容增删改;awk则精于文本分析,支持复杂计算与格式化输出。它们既可独立应对各类任务,又能组合形成强大的文本处理方案,是系统管理员、开发人员提升效率的必备利器 。
grep
什么是grep
在 Linux 系统中,grep
是一款功能强大的文本搜索工具,其核心能力是基于正则表达式匹配目标文本,并将包含匹配内容的行输出(部分环境下匹配内容默认标红显示)。它的全称为Global Regular Expression Print(全局正则表达式打印),支持所有用户直接调用,是命令行文本处理的核心工具之一。
命令格式
grep [选项] '搜索模式' [文件...]
选项:控制 grep 的匹配行为(如忽略大小写、递归搜索等)
搜索模式:指定需要查找的字符串或正则表达式(需用引号括起)
文件:指定要搜索的文件列表(可省略,默认从标准输入读取)
命令参数
选项 | 功能描述 |
---|---|
-A <行数> | After:显示匹配行及其后n 行(形成匹配上下文)。 |
-B <行数> | Before:显示匹配行及其前n 行。 |
-C <行数> | Context:显示匹配行及其前后各n 行(等价于-A n -B n )。 |
-c | Count:只输出匹配的行数,不显示具体内容。 |
-e <模式> | Expression:指定多个匹配模式(逻辑 OR 关系)。 |
-E | Extended:使用扩展正则表达式(支持+ 、? 、| 等元字符)。 |
-f <文件> | File:从文件中读取匹配模式(每行一个模式)。 |
-F | Fixed-string:将模式视为普通字符串(不解析正则),等价于fgrep 。 |
-i | Ignore-case:忽略大小写差异(如Linux 和LINUX 均匹配)。 |
-n | Line-number:显示匹配行的行号。 |
-o | Only-matching:只输出匹配的部分(而非整行)。 |
-q | Quiet:静默模式,不输出任何结果,仅返回退出状态码(0 = 匹配成功)。 |
-s | Silent: suppress 错误信息(如文件不存在时不报错)。 |
-v | Invert-match:反向匹配(显示不匹配的行)。 |
-w | Word-regexp:全词匹配(确保模式是独立单词)。 |
具体实现
[root@hspEdu01 grep]# cat test
aaa
bbbbbb
AAAaaa
BBBBASDFGABBFA
[root@hspEdu01 grep]# grep -A1 b test #匹配识别到b以及后一行
bbbbbb
AAAaaa
[root@hspEdu01 grep]# grep -B1 b test #匹配识别到b以及前一行
aaa
bbbbbb
[root@hspEdu01 grep]# grep -C1 b test #匹配识别到b以及前后各一行
aaa
bbbbbb
AAAaaa
[root@hspEdu01 grep]# grep -c a test # 输出匹配到a的行数
2
[root@hspEdu01 grep]# grep -e b -e a test # 可以多个-e,多次匹配
aaa
bbbbbb
AAAaaa
[root@hspEdu01 grep]# grep -E '^aaa' test # aaa开头的行
aaa
[root@hspEdu01 grep]# grep -E ['^aaa'] test
bbbbbb
AAAaaa
BBBBASDFGABBFA
[root@hspEdu01 grep]# grep -E 'aaa$' test # aaa结尾
aaa
AAAaaa
[root@hspEdu01 grep]# cat grep.txt
aaa
[root@hspEdu01 grep]# grep -f grep.txt test
aaa
AAAaaa
[root@hspEdu01 grep]# cat 1.txt
hello.world
nihao
[root@hspEdu01 grep]# grep '.' 1.txt # 匹配正则表达式
hello.world
nihao
[root@hspEdu01 grep]# grep -F '.' 1.txt # -F 把这个当成匹配而不是正则
hello.world
[root@hspEdu01 grep]# grep -i a test # 不区分大小写
aaa
AAAaaa
BBBBASDFGABBFA
[root@hspEdu01 grep]# grep -n a test
1:aaa
3:AAAaaa
[root@hspEdu01 grep]# grep -o aa test # 仅输出匹配到的部分
aa
aa
[root@hspEdu01 grep]# grep -o aa -q test # -q静默输出
[root@hspEdu01 grep]# echo $? # $?返回上条运行是否成功,0为成功
0
[root@hspEdu01 grep]# grep -s aaa 123.txt # 错误信息
[root@hspEdu01 grep]# echo $?
2
[root@hspEdu01 grep]# grep -w aaa test # 全词匹配
aaa
[root@hspEdu01 grep]# grep -w bbb test
sed
什么是sed
sed
(Stream Editor)是 Linux 系统中强大的文本流编辑器,主要用于过滤、替换、插入、删除文本内容。它逐行处理输入数据(文件或标准输入),执行指定的编辑命令,并将结果输出到标准输出(不修改原文件,除非使用 -i
选项)。
命令格式
sed [选项] '地址范围 命令' [输入文件]
选项:控制 sed
的全局行为(如静默模式、修改原文件等)。
地址范围:指定命令作用的行(如第 3 行、包含error
的行)。
命令:对匹配行执行的操作(如替换、删除、插入)。
输入文件:可选,省略时从标准输入读取数据。
命令参数
常用选项
选项 | 功能描述 |
---|---|
-n | 静默模式:默认会输出所有行,加 -n 后仅通过 p 命令显式打印匹配的行。 |
-e | 多命令执行:对每行依次执行多个编辑命令(可合并为一个 -e 或用分号分隔)。 |
-f <脚本文件> | 从文件读取命令:将编辑命令写入文件(每行一个命令),通过 -f 指定执行。 |
-r (或 -E ) | 扩展正则表达式:支持 + 、? 、() 、| 等元字符(无需转义)。 |
-i | 直接修改原文件(谨慎使用!建议先备份)。 |
-i.bak | 修改原文件并创建备份(如 file.txt → file.txt.bak )。 |
地址范围
地址类型 | 格式 | 示例 |
---|---|---|
无地址 | 不指定 | sed 's/old/new/' |
单行匹配 | 数字 | 3 |
$ | $ | |
/正则表达式/ | /error/ | |
\?正则表达式\? | \?warning\? | |
范围匹配 | start,end | 1,5 |
/start/,/end/ | /BEGIN/,/END/ | |
数字,/正则/ | 3,/error/ | |
/正则/,数字 | /start/,5 | |
步进匹配 | 起始行~步长 | 1~2 |
0~步长 | 0~2 |
编辑命令
命令 | 功能描述 |
---|---|
d | 删除当前行:删除模式空间中的行,并立即进入下一轮循环(不执行后续命令)。 |
p | 打印当前行:输出模式空间中的内容(需配合 -n 选项禁用默认输出)。 |
a\ | 追加文本:在指定行后插入新行(支持 \n 多行)。 |
i\ | 插入文本:在指定行前插入新行(支持 \n 多行)。 |
c\ | 替换整行:将匹配的行替换为指定文本(支持 \n 多行)。 |
w | 写入文件:将匹配的行保存到指定文件。 |
r | 读取文件:在匹配的行后插入指定文件的内容。 |
= | 打印行号:输出当前行的行号。 |
! | 取反操作:对不匹配的行执行命令。 |
s | 查找替换:支持自定义分隔符(如 s@@@ 、s### )和修饰符(如 g 、i )。 |
大小写命令转换
元字符 | 功能描述 |
---|---|
\l | 小写首字符:将下一个字符转为小写。 |
\L | 批量小写:将后续字符转为小写,直到遇到 \U 或 \E 。 |
\u | 大写首字符:将下一个字符转为大写。 |
\U | 批量大写:将后续字符转为大写,直到遇到 \L 或 \E 。 |
\E | 终止转换:停止 \L 或 \U 的效果。 |
具体实现
常用选项演示
[root@hspEdu01 sed]# cat test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed -n '/aa/p' test #输出带有aa的内容
aa
aaabbb
[root@hspEdu01 sed]# sed -e 's/a/A/' -e 's/b/B/' test # -e 多命令执行
Aa
Bbbb
AaaBbb
AABBCCDD
[root@hspEdu01 sed]# cat 1.txt
s/a/A/g
[root@hspEdu01 sed]# sed -f 1.txt test
AA
bbbb
AAAbbb
AABBCCDD
[root@hspEdu01 sed]# sed 's/a\+/A/g' test # 不带-r,'+'需要转义'\+'
A
bbbb
Abbb
AABBCCDD
[root@hspEdu01 sed]# sed -r 's/a+/A/g' test # 带-r,'+'不需要转义
A
bbbb
Abbb
AABBCCDD
[root@hspEdu01 sed]# sed -i.bak -r 's/a+/X/g' test # a+一次或多次a
[root@hspEdu01 sed]# cat test
X
bbbb
Xbbb
AABBCCDD
[root@hspEdu01 sed]# ls
1.txt test test.bak
地址范围演示
[root@hspEdu01 sed]# cat test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed -n 'p' test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed -n '2p' test
bbbb
[root@hspEdu01 sed]# sed -n '$p' test
AABBCCDD
[root@hspEdu01 sed]# sed -n '/aa/p' test
aa
aaabbb
[root@hspEdu01 sed]# sed -n '1,3p' test
aa
bbbb
aaabbb
[root@hspEdu01 sed]# sed -n '3,/AA/p' test #输出第三行-出现AA的行
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed -n '/bbbb/,3p' test
bbbb
aaabbb
[root@hspEdu01 sed]# sed -n '1~2p' test # 输出奇数行
aa
aaabbb
[root@hspEdu01 sed]# sed -n '0~2p' test # 输出偶数行
bbbb
AABBCCDD
编辑命令演示
[root@hspEdu01 sed]# cat test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed '2d' test
aa
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed '/aa/d' test
bbbb
AABBCCDD
[root@hspEdu01 sed]# sed '2a第二行' test
aa
bbbb
第二行
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed 'a每一行' test
aa
每一行
bbbb
每一行
aaabbb
每一行
AABBCCDD
每一行
[root@hspEdu01 sed]# sed '/bb/ibb行' test
aa
bb行
bbbb
bb行
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed '2c新内容' test
aa
新内容
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed '/aa/w aa.txt' test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# cat aa.txt
aa
aaabbb
[root@hspEdu01 sed]# sed '/aa/r aa.txt' test
aa
aa
aaabbb
bbbb
aaabbb
aa
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed -n '/aa/=' test
1
3
[root@hspEdu01 sed]# sed -n '=;p' test
1
aa
2
bbbb
3
aaabbb
4
AABBCCDD
[root@hspEdu01 sed]# sed -n '/aa/!p' test
bbbb
AABBCCDD
[root@hspEdu01 sed]# sed -e 's/a/A/' -e 's/b/B/' test
Aa
Bbbb
AaaBbb
AABBCCDD
[root@hspEdu01 sed]# sed -e 's/a/A/g' -e 's/b/B/g' test # g 全局替换
AA
BBBB
AAABBB
AABBCCDD
大小写命令转换演示
[root@hspEdu01 sed]# cat test
aa
bbbb
aaabbb
AABBCCDD
[root@hspEdu01 sed]# sed 's/\(AABB\)CCDD/\1\lCCDD/' test # \1匹配第一个括号的内容,\l后面第一个字符变小写
aa
bbbb
aaabbb
AABBcCDD
[root@hspEdu01 sed]# sed 's/\(AABB\)CCDD/\1\LCCDD/' test # \L 后面匹配到的都变小写
aa
bbbb
aaabbb
AABBccdd
[root@hspEdu01 sed]# sed 's/\(AABB\)CCDD/\1\LCC\UDD/' test # \U,\E 停止
aa
bbbb
aaabbb
AABBccDD
[root@hspEdu01 sed]# sed 's/\(aaa\)bbb/\1\ubbb/' test
aa
bbbb
aaaBbb
AABBCCDD
[root@hspEdu01 sed]# sed 's/\(aaa\)bbb/\1\Ubbb/' test
aa
bbbb
aaaBBB
AABBCCDD
补充命令
命令 | 功能描述 | 示例(文件内容:1.abc\n2.def\n3.ghi ) | 执行后效果 |
---|---|---|---|
空间操作 | |||
h | 将模式空间内容覆盖到保持空间。 | sed -n '1h; 2{x; p}' | 打印第 1 行(abc ) |
H | 将模式空间内容追加到保持空间(用 \n 分隔)。 | sed -n '{H; $x; p}' | 逆序输出(ghi\ndef\nabc ) |
g | 将保持空间内容覆盖到模式空间。 | sed '1h; 2,$g' | 第 2 行及后续行替换为第 1 行(abc ) |
G | 将保持空间内容追加到模式空间(用 \n 分隔)。 | sed '1h; 2G' | 第 2 行变为 def\nabc |
x | 交换模式空间与保持空间的内容。 | sed -n '{h; n; x; p}' | 只打印偶数行(def ) |
行控制 | |||
n | 读取下一行覆盖模式空间,跳过当前行后续命令。 | sed '/abc/{n; s/def/X/}' | 第 2 行变为 X |
N | 读取下一行追加到模式空间(用 \n 分隔),继续处理当前命令。 | sed -n '/abc/{N; p}' | 打印第 1+2 行(abc\ndef ) |
d | 删除模式空间内容,立即处理下一行(跳过后续命令)。 | sed '/def/d' | 删除第 2 行(输出:1.abc\n3.ghi ) |
D | 删除模式空间中到第一个 \n 的内容,并重新执行当前命令。 | sed '/abc/{N; D}' | 删除第 1+2 行(输出:3.ghi ) |
awk
什么是awk
awk 是一种强大的文本处理工具,最初用于 Unix 系统,现已广泛应用于 Linux、macOS 等操作系统。它以行为基本处理单位,结合内置函数和编程语法,能高效地对文本数据进行过滤、提取、转换、统计等操作,尤其适合处理结构化数据(如日志文件、CSV/TSV 文件等)。
命令格式
awk [选项] '模式 { 动作 }' 输入文件1 输入文件2 ...
选项:
模式:用于筛选行的条件(如 /正则表达式/
、行号
、条件表达式
)。
动作:对匹配行执行的操作(用 { }
包裹)。
命令参数
常用命令行参数
参数 | 功能描述 |
---|---|
-F 分隔符 | 指定字段分隔符(覆盖默认的空格或制表符)。 |
-v 变量=值 | 定义变量,用于在 awk 脚本中使用。 |
-f 脚本文件 | 从文件读取 awk 代码(适用于复杂脚本)。 |
-W 选项 | 指定扩展选项(如 --posix 启用 POSIX 兼容模式)。 |
-i 模块 | 加载扩展模块(如 gawk 的 time 模块)。 |
内置变量
变量 | 含义 |
---|---|
$0 | 当前整行内容。 |
$n | 第 n 个字段($1 为第一列,$NF 为最后一列)。 |
NF | 当前行的字段数。 |
NR | 当前处理的行号(全局计数)。 |
FNR | 当前文件的行号(处理多文件时重置)。 |
FS | 输入字段分隔符(默认是空格或制表符)。 |
OFS | 输出字段分隔符(默认是空格)。 |
RS | 行分隔符(默认是换行符 \n )。 |
ORS | 输出行分隔符(默认是换行符)。 |
FILENAME | 当前处理的文件名。 |
具体实现
[root@hspEdu01 awk]# cat test
hello:world
linux:redhat:lalala:hahaha
along:love:youo
[root@hspEdu01 awk]# awk -v FS=':' '{print $1,$2}' test # FS指定输入分隔符
hello world
linux redhat
along love
[root@hspEdu01 awk]# awk -v FS=':' -v OFS='---' '{print $1,$2}' test # OFS指定输出分隔符
hello---world
linux---redhat
along---love
[root@hspEdu01 awk]# awk -v RS=':' '{print $1,$2}' test
hello
world linux
redhat
lalala
hahaha along
love
youo
[root@hspEdu01 awk]# awk -v FS=':' -v ORS='---' '{print $1,$2}' test
hello world---linux redhat---along love---
[root@hspEdu01 awk]# awk -F: '{print NF}' test
2
4
3
[root@hspEdu01 awk]# awk -F: '{print $(NF-1)}' test # 显示倒数第2列
hello
lalala
love
[root@hspEdu01 awk]# awk '{print NR}' test 1.txt
1
2
3
[root@hspEdu01 awk]# awk '{print NR}' test
1
2
3
[root@hspEdu01 awk]# awk '{print NR}' test test
1
2
3
4
5
6
[root@hspEdu01 awk]# awk '{print FILENAME}' test
test
test
test
[root@hspEdu01 awk]# awk 'BEGIN {print ARGC}' test
2
[root@hspEdu01 awk]# awk 'BEGIN {print ARGC}' test test
3
[root@hspEdu01 awk]# awk 'BEGIN {print ARGV[0]}' test test
awk
[root@hspEdu01 awk]# awk 'BEGIN {print ARGV[1]}' test test
test
[root@hspEdu01 awk]# awk 'BEGIN {print ARGV[2]}' test test
test
结语
Linux 三剑客的魅力,远不止于本文所述的基础用法。当你尝试用 awk
编写自定义函数,用 sed
实现状态机逻辑,或用 grep
结合 pcre
处理复杂正则时,会发现这三个工具的边界在不断拓展。
技术的终极答案,永远藏在探索之中。不妨带着「如何用一行命令实现更复杂的逻辑」的疑问,继续深挖三剑客的高级特性,甚至尝试用它们解决看似「不属于文本处理」的问题 —— 你会发现,文本的边界,就是思维的边界。