在掌握grep和正则表达式之后,我们接着学习Linux命令行文本处理的另外两大核心工具:sed 和 awk 。grep 擅长查找,而 sed 擅长编辑,awk 则擅长格式化报告和复杂的数据处理。
sed
是一个非交互式的流编辑器。它逐行读取文本,根据预设的规则对每行进行处理,并将结果输出到标准输出。默认不修改原始文件。
基本语法: sed [选项] '地址 命令' 文件名
3
)、范围 (如 2,5
) 或正则表达式 (如 /pattern/
)。若省略,则应用于所有行。常用命令:
# 删除文件的第3行
sed '3d' /etc/passwd
# 删除文件第2到第5行
sed '2,5d' /etc/passwd
# 删除所有包含 "nologin" 字符串的行
sed '/nologin/d' /etc/passwd
p
命令通常与 -n
选项配合使用。-n
会禁止 sed
的默认输出,从而只打印被 p
命令明确指定的行。
# 只打印文件的第3行
sed -n '3p' /etc/passwd
# 只打印包含 "root" 的行 (效果类似 grep)
sed -n '/root/p' /etc/passwd
这是 sed
最强大的命令。
语法: 's/pattern/replacement/flags'
pattern
: 要匹配的正则表达式。replacement
: 要替换成的字符串。&
符号在replacement
中代表被匹配到的整个内容。flags
:g
: 全局替换行内的所有匹配。i
: 忽略大小写。 数字 (如2
): 只替换每行中第 N 次出现的匹配。
代码示例:
# 将每行第一个 "root" 替换为 "admin"
sed 's/root/admin/' /etc/passwd
# 将所有 "nologin" 替换为 "disabled"
sed 's/nologin/disabled/g' /etc/passwd
# 给所有数字加上方括号
echo "line 123 has number 456" | sed 's/[0-9][0-9]*/[&]/g'
# 使用 -i 选项直接修改文件 (危险操作,建议先备份)
sed -i.bak 's/old_text/new_text/g' /path/to/your/file
# (-i.bak 会创建一个 .bak 后缀的备份文件)
awk
是一个强大的文本处理语言,它逐行读取输入,并将每行按分隔符切分成字段,极度擅长处理列式数据和生成报告。
基本语法: awk '[选项] 'pattern { action }' 文件名
核心概念:
Record: 默认情况下,每行是一个记录。 Field: 每个记录被分隔符切分成的部分。通过 1, 2, 3 … 引用,0 代表整行。 FS: 输入字段的分隔符。 NR: 当前记录的行号。 NF: 当前记录的字段数量。
Pattern (模式): 决定是否对当前行执行 action
。可以是正则表达式、条件表达式或特殊的 BEGIN
/ END
。
Action (动作): 花括号 {}
中包含的一系列命令。
常用命令与功能:
# 打印 /etc/passwd 文件的第一列 (用户名)
awk -F: '{print $1}' /etc/passwd
# 打印 /etc/passwd 文件的第一列和最后一列
awk -F: '{print "User:", $1, "| Shell:", $NF}' /etc/passwd
-F:
: 指定字段分隔符为冒号。# 只打印包含 "root" 的行
awk '/root/' /etc/passwd
# 只打印第三个字段(UID)小于10的行
awk -F: '$3 < 10 {print $0}' /etc/passwd
# 只打印奇数行
awk 'NR % 2 == 1' /etc/passwd
BEGIN
和 END
模式BEGIN { ... }
: 在处理任何行之前执行,用于初始化或打印表头。END { ... }
: 在处理完所有行之后执行,用于计算汇总和打印结果。代码示例:
# 统计 /etc/passwd 文件的用户总数
awk 'END {print "Total users:", NR}' /etc/passwd
# 打印磁盘使用情况报告,并添加表头
df -h | awk 'BEGIN {printf "%-30s %-10s %-10s\n", "Filesystem", "Size", "Used%"} NR>1 {printf "%-30s %-10s %-10s\n", $1, $2, $5}'
本次我们深入学习了Linux文本处理三剑客中的
sed
和awk
。sed
作为流编辑器,其核心优势在于对文本行进行删除、打印和替换操作。而awk
则更像一个微型编程语言,它按字段处理数据,擅长从结构化文本中提取信息、计算、生成格式化的报告。在实际工作中,经常将grep
,sed
,awk
通过管道组合使用,以完成复杂的文本处理任务。
背景文件 server.log
内容:
2024-08-08 10:00:15 INFO: User 'alice' logged in from 192.168.1.10.
2024-08-08 10:02:30 DEBUG: System check initiated.
2024-08-08 10:03:05 WARNING: Disk space is running low on /dev/sda1.
2024-08-08 10:05:45 INFO: User 'bob' accessed resource 'file.txt'.
2024-08-08 10:06:22 ERROR: Failed to connect to database 'prod_db'.
题目:
sed
命令,删除 server.log
中所有 DEBUG
级别的日志行。sed
命令,只打印出 server.log
文件的第 2 到第 4 行。sed
命令,将 server.log
中所有出现的 “User” (首字母大写) 替换为 “Client”。server.log
的日志级别是第3个字段 (以空格为分隔符)。请使用 awk
命令,打印出所有日志行的日期 (第1个字段) 和日志级别。awk
命令,只打印 server.log
中包含 ERROR
信息的完整日志行。awk
命令,打印 server.log
中字段数超过8个的所有行。awk
命令,统计 server.log
中 INFO
, WARNING
, ERROR
日志各自出现的次数。sed
命令,将 server.log
中所有 INFO
日志行的行首添加 [INFO_LOG]
前缀。sed
过滤出 server.log
中所有 INFO
级别的日志,然后用 awk
提取并打印出用户名 (假设用户名总是在单引号 ' '
中)。sed
命令,只替换 server.log
中每行第二次出现的冒号 :
为分号 ;
。sed '/DEBUG:/d' server.log
'/DEBUG:/d'
使用正则表达式 /DEBUG:/
作为地址,匹配所有包含 “DEBUG:” 的行,并用 d
命令删除它们。sed -n '2,4p' server.log
-n
禁止默认输出。2,4
是行号范围地址,p
命令只打印这个范围内的行。sed 's/User/Client/g' server.log
s/User/Client/g
将所有出现的 “User” 替换为 “Client”。g
标志确保全局替换。awk '{print $1, $3}' server.log
awk '/ERROR/' server.log
awk
的模式部分如果没有对应的 { action }
,则默认动作就是 {print $0}
(打印整行)。/ERROR/
匹配包含 “ERROR” 的行。awk 'NF > 8' server.log
NF > 8
是一个条件模式,NF
是当前行的字段数。只有当字段数大于8时,条件为真,执行默认的打印整行动作。awk '/INFO/ {info_count++} /WARNING/ {warn_count++} /ERROR/ {error_count++} END {print "INFO:", info_count, "WARNING:", warn_count, "ERROR:", error_count}' server.log
awk
可以有多个 pattern { action }
组合。它会遍历每一行,匹配对应的模式并执行动作 (累加计数器)。END
块在最后打印所有计数器的汇总结果。sed '/INFO/s/^/[INFO_LOG] /' server.log
/INFO/
是地址,表示只对包含 “INFO” 的行执行命令。s/^/[INFO_LOG] /
是替换命令,^
匹配行首,将其替换为指定的前缀。sed -n '/INFO/p' server.log | awk -F"'" '{print $2}'
解析:
sed -n '/INFO/p' server.log
: 首先过滤出所有INFO
日志行。|
: 管道将结果传给awk
。sed 's/:/;/2' server.log
s/pattern/replacement/flags
中的 flags
可以是一个数字。2
表示只替换每行中第二次出现的匹配项。日期:2025年8月12日 专栏:Linux教程