在掌握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/passwdp 命令通常与 -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/passwdBEGIN 和 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.logs/User/Client/g 将所有出现的 “User” 替换为 “Client”。g 标志确保全局替换。awk '{print $1, $3}' server.logawk '/ERROR/' server.logawk 的模式部分如果没有对应的 { action },则默认动作就是 {print $0} (打印整行)。/ERROR/ 匹配包含 “ERROR” 的行。awk 'NF > 8' server.logNF > 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.logawk 可以有多个 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.logs/pattern/replacement/flags 中的 flags 可以是一个数字。2 表示只替换每行中第二次出现的匹配项。日期:2025年8月12日 专栏:Linux教程