Linux 文本处理三剑客:awk、grep、sed 完全指南
1. 概述
Linux 系统提供了三个强大的文本处理工具:awk、grep 和 sed,它们各有所长,结合使用可以高效地处理文本数据。
- awk:擅长文本分析和格式化输出,是一门强大的脚本语言。
- grep:擅长文本搜索和过滤。
- sed:擅长文本编辑和转换。
这三个工具都支持正则表达式,可以处理标准输入和文件输入,是 Shell 脚本编程中不可或缺的工具。
2. awk 使用指南
2.1 基本介绍
awk 是一种编程语言,专门用于文本处理和数据提取,支持变量、条件判断、循环等编程特性。其名称来源于三位创始人的姓氏首字母。
2.2 基本语法
awk '模式 { 动作 }' [输入文件...]
命令 | awk '模式 { 动作 }'
2.3 工作原理
awk 按行处理文本,每行被分割成多个字段:
$0
:整行内容$1
:第一个字段$2
:第二个字段- …
2.4 常用选项
选项 | 说明 | 示例 |
---|---|---|
-F | 指定输入字段分隔符 | awk -F: '{print $1}' /etc/passwd |
-v | 定义变量 | awk -v var=10 '{print $1 + var}' file |
-f | 从脚本文件中读取 awk 命令 | awk -f script.awk data.txt |
2.5 内置变量
变量 | 说明 | 示例 |
---|---|---|
FS | 输入字段分隔符(默认空格) | awk 'BEGIN{FS=":"}{print $1}' file |
OFS | 输出字段分隔符(默认空格) | awk 'BEGIN{OFS="-"}{print $1,$2}' file |
RS | 输入记录分隔符(默认换行符) | awk 'BEGIN{RS=";"}{print}' file |
ORS | 输出记录分隔符(默认换行符) | awk 'BEGIN{ORS="\n\n"}{print}' file |
NF | 当前行的字段数量 | awk '{if(NF>5) print $0}' file |
NR | 当前处理的总行号 | awk '{print NR, $0}' file |
FNR | 当前文件中的行号 | awk '{print FNR, $0}' file1 file2 |
FILENAME | 当前文件名 | awk '{print FILENAME, $0}' file |
2.6 示例
# 打印指定列(源文档示例)
awk '{print $1, $3}' file.txt# 指定分隔符(源文档示例)
awk -F: '{print $1, $6}' /etc/passwd# 使用条件过滤(源文档示例)
awk '$3 > 1000 {print $1}' /etc/passwd# 计算数值总和(源文档示例)
awk '{sum += $1} END {print sum}' file.txt# 使用BEGIN和END块(源文档示例)
awk 'BEGIN {print "开始处理"} {print $0} END {print "处理完成"}' file.txt# 使用内置变量(源文档示例)
awk '{print "行号:", NR, "字段数:", NF, "内容:", $0}' file.txt# 打印雇员信息(源文档示例)
awk '{ print }' employee.txt# 输出特定行(源文档示例)
awk '/张三/ { print }' employee.txt# 统计满足特定条件的记录数(源文档示例)
awk '/术/ { count=count+1 } END { print "Count="count }' employee.txt# 格式化输出表格(源文档综合示例)
awk 'BEGIN { printf "序号\t名字\t部门\t年龄\n-------------------\n" } { print } END {printf "-------------------\n"}' employee.txt
2.7 高级用法
# 使用数组统计词频(源文档示例)
awk '{for(i=1;i<=NF;i++) count[$i]++} END {for(word in count) print word, count[word]}' file.txt | sort -k2 -nr# 条件判断(源文档示例)
awk '{if($3 > 1000) print "用户:", $1, "UID:", $3; else print "系统用户:", $1}' /etc/passwd# 循环处理(源文档示例)
awk '{for(i=NF;i>=1;i--) printf "%s ", $i; printf "\n"}' file.txt# 9x9乘法表(源文档示例)
awk 'BEGIN {for(i=1;i<=9;i++){for(j=1;j<=i;j++) printf "%d*%d=%-2d ",j,i,j*i; print}}'
3. grep 使用指南
3.1 基本介绍
grep (Global Regular Expression Print) 用于在文本中搜索匹配指定模式的行。
3.2 基本语法
grep [选项] 模式 [文件...]
命令 | grep [选项] 模式
3.3 常用选项
选项 | 说明 | 示例 |
---|---|---|
-i | 忽略大小写 | grep -i 'hello' file.txt |
-v | 反向匹配,显示不匹配的行 | grep -v '^#' config.conf |
-n | 显示行号 | grep -n 'error' logfile.txt |
-c | 只显示匹配的行数 | grep -c 'pattern' data.txt |
-r | 递归搜索目录 | grep -r 'function' /path/to/code/ |
-l | 只显示包含匹配的文件名 | grep -l 'TODO' *.py |
-E | 使用扩展正则表达式 | `grep -E '(error |
-A n | 显示匹配行及其后n行 | grep -A 3 'Exception' traceback.log |
-B n | 显示匹配行及其前n行 | grep -B 2 'segmentation fault' system.log |
-C n | 显示匹配行及其前后各n行 | grep -C 2 'keyword' file.txt |
3.4 示例
# 搜索包含"error"的行(源文档示例)
grep 'error' logfile.txt# 忽略大小写搜索(源文档示例)
grep -i 'error' logfile.txt# 显示行号(源文档示例)
grep -n 'error' logfile.txt# 搜索并显示后3行内容(源文档示例)
grep -A 3 'error' logfile.txt# 递归搜索目录(源文档示例)
grep -r 'function' /path/to/code/# 使用扩展正则表达式(源文档示例)
grep -E '(error|warning)' logfile.txt# 统计文件中包含特定模式的记录数(源文档awk示例的grep等效)
grep -c 'pattern' employee.txt# 输出总长度大于10的行(源文档awk示例的grep等效)
grep '.\{11,\}' employee.txt
4. sed 使用指南
4.1 基本介绍
sed (Stream EDitor) 是一个流编辑器,用于对文本进行非交互式的编辑。
4.2 基本语法
sed [选项] '命令' [输入文件...]
命令 | sed [选项] '命令'
4.3 常用选项
选项 | 说明 | 示例 | |
---|---|---|---|
-n | 抑制自动输出,只显示处理过的行 | sed -n '10p' file.txt | |
-e | 允许多个编辑命令 | sed -e 's/foo/bar/' -e '/baz/d' file | |
-i | 直接修改文件内容 | sed -i.bak 's/old/new/g' file.txt | |
-r | 使用扩展正则表达式 | `sed -r 's/(foo | bar)/YES/g’ file` |
4.4 常用命令
命令 | 说明 | 示例 |
---|---|---|
s/模式/替换/标志 | 替换操作 | sed 's/old/new/g' file.txt |
p | 打印 | sed -n '1,5p' file.txt |
d | 删除 | sed '/pattern/d' file.txt |
a\文本 | 在行后追加文本 | sed '$a\追加到最后一行' file.txt |
i\文本 | 在行前插入文本 | sed '1i\插入到第一行' file.txt |
c\文本 | 替换整行 | sed '/pattern/c\新的整行内容' file.txt |
4.5 示例
# 替换文本(源文档示例)
sed 's/old/new/g' file.txt# 删除空行(源文档示例)
sed '/^$/d' file.txt# 直接修改文件(源文档示例)
sed -i 's/old/new/g' file.txt# 打印特定行(源文档示例)
sed -n '10,20p' file.txt# 多重编辑(源文档示例)
sed -e 's/foo/bar/g' -e '/baz/d' file.txt# 在匹配行后追加内容(源文档示例)
sed '/pattern/a\追加的内容' file.txt# 模拟cat命令打印文件内容(源文档示例)
sed '' data.txt# 从标准输入中读取数据(源文档示例)
echo "hello world" | sed ''# 使用脚本文件(源文档示例)
echo -e "1d\n2d\n5d" > scripts
sed -f scripts data.txt
5. 综合应用示例
5.1 日志分析
# 分析日志中的错误,统计每种错误的数量(源文档grep示例扩展)
grep 'ERROR' application.log | awk '{print $5}' | sort | uniq -c | sort -nr# 提取最近一小时的日志并分析(源文档sed示例扩展)
sed -n "/$(date -d '1 hour ago' '+%H:%M:%S')/,\$p" application.log | grep 'ERROR' | awk '{print $5}' | sort | uniq -c
5.2 数据提取和转换
# 从CSV文件中提取特定列并转换格式(源文档awk示例扩展)
awk -F, '{print $1 "," $3 "," $5}' data.csv | sed 's/旧值/新值/g' > processed_data.csv# 提取网页中的链接(源文档grep示例扩展)
curl -s http://example.com | grep -o 'href="[^"]*"' | sed 's/href="//;s/"$//' | awk '!/^#/ && !/^javascript:/'# 生成格式化的文本报告(源文档awk综合示例扩展)
awk 'BEGIN {printf "序号\t名字\t部门\t年龄\n-------------------\n"} {printf "%s\t%s\t%s\t%s\n", $1, $2, $3, $4} END {printf "-------------------\n"}' employee.txt
5.3 系统监控
# 监控进程内存使用(源文档awk示例扩展)
ps aux | awk '{if($4 > 5.0) print "进程:", $11, "内存使用:", $4"%"}'# 分析磁盘使用情况(源文档awk示例扩展)
df -h | awk '/\/dev\/sd/ {print "分区:", $1, "使用率:", $5, "可用空间:", $4}'# 检查系统用户(源文档awk示例扩展)
awk -F: '$3 < 1000 {print "系统用户:", $1} $3 >= 1000 {print "普通用户:", $1}' /etc/passwd
6. 正则表达式参考
6.1 基本元字符
元字符 | 说明 |
---|---|
. | 匹配任意单个字符 |
* | 匹配前一个字符0次或多次 |
+ | 匹配前一个字符1次或多次 |
? | 匹配前一个字符0次或1次 |
^ | 匹配行首 |
$ | 匹配行尾 |
[] | 匹配括号内的任意字符 |
[^] | 不匹配括号内的任意字符 |
` | ` |
() | 分组 |
6.2 字符类
字符类 | 说明 |
---|---|
[[:alpha:]] | 字母字符 |
[[:digit:]] | 数字字符 |
[[:alnum:]] | 字母数字字符 |
[[:space:]] | 空白字符 |
[[:lower:]] | 小写字母 |
[[:upper:]] | 大写字母 |
6.3 转义字符
转义序列 | 说明 |
---|---|
\n | 换行符 |
\t | 制表符 |
\s | 空白字符 |
\S | 非空白字符 |
\w | 单词字符 |
\W | 非单词字符 |
\d | 数字字符 |
\D | 非数字字符 |
7. 总结与速查
7.1 工具选择指南
- 搜索文本:使用 grep
- 编辑文本:使用 sed
- 处理结构化数据:使用 awk
- 复杂文本处理:结合使用三者
7.2 常用命令速查
awk 常用命令
awk '{print $1}' file # 打印第一列
awk -F: '{print $1}' file # 指定冒号分隔符并打印第一列
awk 'NR==10' file # 打印第10行
awk '$1 > 100' file # 过滤第一列大于100的行
awk '{sum+=$1} END{print sum}' file # 对第一列求和
awk 'BEGIN{FS=":";OFS="-"}{print $1,$3}' file # 设置输入输出分隔符并打印
awk '/pattern/{count++} END{print count}' file # 统计模式出现次数
grep 常用命令
grep pattern file # 基本搜索
grep -i pattern file # 忽略大小写
grep -v pattern file # 反向匹配
grep -n pattern file # 显示行号
grep -r pattern dir # 递归搜索
grep -E "pattern1|pattern2" file # 扩展正则表达式(或)
grep -c pattern file # 统计匹配行数
grep -A n pattern file # 显示匹配行及后n行
sed 常用命令
sed 's/old/new/g' file # 全局替换
sed '/pattern/d' file # 删除匹配行
sed -n '10,20p' file # 打印10-20行
sed -i.bak 's/old/new/' file # 直接修改文件并备份原文件
sed '/^#/d; /^$/d' file # 删除注释和空行
sed '1,5s/old/new/g' file # 替换1-5行的内容
sed '/pattern/a\text' file # 在匹配行后追加文本
7.3 性能优化技巧
- 尽量使用最简单的正则表达式
- 在 grep 中使用
-F
选项处理固定字符串 - 在 awk 中预先处理数据减少后续操作
- 使用管道连接多个简单操作而不是一个复杂操作
- 对于大文件,考虑使用
split
分割后并行处理
7.4 常见问题解决
- 特殊字符处理:使用转义字符或不同的定界符(如
s#old#new#
) - 跨行匹配:使用 sed 的
N
、D
命令或 awk 的RS
变量 - 性能问题:优化正则表达式,减少回溯
- 编码问题:确保终端和文件编码一致
通过掌握这三款工具的组合使用,可以解决 Linux 环境下绝大多数文本处理需求,大大提高工作效率。本文档涵盖了源文档中的主要示例和用法,并添加了选项示例,可以作为日常参考和学习的指南。