
Linux系统中的grep、sed和awk是三个强大的文本处理工具,它们各自具有独特的功能和应用场景。本文将详细介绍这三个命令的使用方法和常见应用场景。
grep - 文本搜索利器
grep(Global Regular Expression Print)命令用于在文件中搜索指定的文本模式。它是最基础也是最常用的文本搜索工具,默认是按行搜索的。
基本语法
grep [选项] 模式 文件名
常用选项
选项 | 说明 | 示例 | 示例说明 |
---|---|---|---|
-i | 忽略大小写 | grep -i "Error" file.txt | 忽略“Error”的大小写 |
-v | 显示不匹配的行 | grep -v "error" file.txt | 显示不匹配“error”的行 |
-n | 显示行号 | grep -n "error" file.txt | 显示匹配行及其行号,如 “123:error occurred” |
-l | 只显示包含匹配的文件名 | grep -l "error" *.txt | 只列出包含 “error” 的文件名,如 “log.txt” |
-L | 只显示不包含匹配的文件名 | grep -L "error" *.txt | 只列出不包含 “error” 的文件名,如 “success.txt” |
-c | 只显示匹配行的数量 | grep -c "error" file.txt | 显示文件中包含 “error” 的行数,如 “5” |
-w | 只匹配整个单词 | grep -w "error" file.txt | 匹配 “error” 但不匹配 “errors” 或 “errorlog” |
-x | 只匹配整行(精确匹配整行) | grep -x "error" file.txt | 只匹配整行恰好是 “error” 的行,不匹配 “error log” |
-r | 递归搜索目录(不跟随符号链接) | grep -r "error" /path | 在 /path 目录下递归搜索,不包含符号链接指向的目录 |
-R | 递归搜索(跟随符号链接) | grep -R "error" /path | 在 /path 目录下递归搜索,包含符号链接指向的目录 |
-A n | 显示匹配行及后 n 行 | grep -A 2 "error" file.txt | 显示包含 “error” 的行及其后 2 行 |
-B n | 显示匹配行及前 n 行 | grep -B 2 "error" file.txt | 显示包含 “error” 的行及其前 2 行 |
-C n | 显示匹配行及前后各 n 行 | grep -C 2 "error" file.txt | 显示包含 “error” 的行及其前后各 2 行 |
grep 可以组合使用多个选项,例如:
# 忽略大小写 + 显示行号
grep -in "error" file.txt
# 递归搜索 + 显示行号 + 只显示文件名
grep -rln "error" /path/to/dir
# 显示行号 + 匹配整词 + 显示上下文
grep -nw -C 2 "error" file.txt
使用示例
# 在文件中搜索包含"error"的行
grep "error" log.txt
# 忽略大小写搜索
grep -i "ERROR" log.txt
# 显示行号
grep -n "error" log.txt
# 递归搜索目录
grep -r "TODO" ./src/
# 使用正则表达式
grep "^[0-9]" data.txt
sed - 流编辑器
sed(Stream Editor)是一个强大的文本流编辑器,可以对文本进行替换、删除、插入等操作。
基本语法
sed [选项] '[地址]命令[参数]' 文件名
- 地址:指定要操作的行(可选),可以是
- 行号(如
1
表示第1行,$
表示最后一行) - 正则表达式(如
/pattern/
表示匹配pattern
的行) - 行范围(如
1,5
表示第1到第5行)
- 行号(如
- 命令:指定要执行的操作(必选),常用命令有s、d、p等。
- 参数:命令的附加参数(可选),用于进一步控制命令的行为,比如:
g
:全局替换(用于s
命令)。2
:只替换第2个匹配(用于s
命令)。i
:忽略大小写(用于正则表达式)。
常用选项
-i
: 直接修改文件内容(慎用,会覆盖原文件)。-n
: 禁止自动输出,只打印被处理的行(通常与p
命令一起使用)。-e
: 执行多个命令-f
: 从文件读取命令
常用命令
命令 | 解释 | 说明 | 是否需要分隔符 | 常见使用方式 | 常见使用方式解释 |
---|---|---|---|---|---|
s | substitute | 替换 | 是 | sed ’s/old/new/’ 文件 | s 后面的 /old/new/ 是替换命令的具体内容,它定义了替换操作的细节,s 命令的完整格式是s<分隔符>查找模式<分隔符>替换内容<分隔符> 。s/old/new/ 中地址是隐式的,表示所有行。 |
d | delete | 删除 | 否 | sed ‘/pattern/d’ 文件 | /pattern/ 为地址部分,是 sed 中的地址匹配语法,pattern是一个正则表达式;命令为d 。 |
p | 打印 | 否 | sed -n ‘/pattern/p’ 文件 | /pattern/ 为地址部分,是 sed 中的地址匹配语法,pattern是一个正则表达式;命令为p 。 | |
i | insert | 在匹配行之前插入内容 | 否 | sed ‘/pattern/i 新内容’ 文件 | /pattern/ 为地址部分,是 sed 中的地址匹配语法,pattern是一个正则表达式;命令为i 。 |
a | append | 在匹配行之后追加内容 | 否 | sed ‘/pattern/a 新内容’ 文件 | /pattern/ 为地址部分,是 sed 中的地址匹配语法,pattern是一个正则表达式;命令为a 。 |
c | change | 用新内容替换整行 | 否 | sed ‘/pattern/c 新内容’ 文件 | /pattern/ 为地址部分,是 sed 中的地址匹配语法,pattern是一个正则表达式;命令为c 。 |
注意,s命令的默认分隔符是 /
,但可以使用其他符号(如 |
、:
等)作为分隔符,当/
有其他作用时,如表示文件路径,可以使用自定义分隔符。示例:
# 使用默认分隔符
sed 's/old/new/' file.txt
# 使用自定义分隔符
sed 's|old|new|' file.txt
sed 's:old🆕' file.txt
使用示例
# 替换文本
sed 's/old/new/' file.txt
sed 's/old/new/g' file.txt # 全局替换
# 删除空行
sed '/^$/d' file.txt
# 打印特定行
sed -n '1,5p' file.txt
# 直接修改文件
sed -i 's/old/new/g' file.txt
# 多个命令组合
sed -e 's/old/new/' -e 's/foo/bar/' file.txt
awk - 文本处理编程语言
awk是一个强大的文本处理编程语言,特别适合处理格式化的文本数据。
基本语法
awk [选项] '模式 {动作}' 文件名
- 模式 pattern:决定何时执行action
- 动作 action:在pattern匹配时要执行的操作
常用选项
选项 | 说明 | 示例 | 示例说明 |
---|---|---|---|
-F | 指定字段分隔符 | awk -F: '{ print $1 }' /etc/passwd | 使用冒号作为分隔符 |
-f | 从文件读取 awk 脚本 | awk -f script.awk data.txt | 从 script.awk 读取脚本 |
-v | 设置变量 | awk -v name="John" '{ print name }' file.txt | 设置变量 name 的值为 “John” |
常用内置变量
内置变量让我们能更方便地处理文本和控制程序行为
变量名称 | 说明 | 使用示例 | 使用示例说明 |
---|---|---|---|
$0 | 整行内容 | awk '{ print $0 }' file.txt | 打印文件的每一行内容 |
$1,$2… | 第n个字段 | awk '{ print $1, $3 }' file.txt | 打印每行的第1和第3个字段 |
NF | 字段数量 | awk '{ print NF, $0 }' file.txt | 打印每行的字段数量及内容 |
NR | 当前行号 | awk '{ print "Line " NR ":", $0 }' file.txt | 打印行号和行内容 |
FS | 输入字段分隔符 | awk 'BEGIN { FS=":" } { print $1 }' /etc/passwd | 使用冒号作为分隔符读取passwd文件 |
OFS | 输出字段分隔符 | awk 'BEGIN { OFS=" -> " } { print $1, $2 }' file.txt | 输出字段之间使用 " -> " 分隔 |
RS | 记录分隔符 | awk 'BEGIN { RS="" } { print $0 }' file.txt | 使用空行作为记录分隔符(段落模式) |
模式类型
正则表达式模式
在 awk 中,正则表达式模式需要用 /
包裹。
# 匹配包含 "error" 的行
awk '/error/ { print $0 }' log.txt
# 匹配以 "root" 开头的行
awk '/^root/ { print $0 }' /etc/passwd
关系表达式模式
# 第三列大于 100
awk '$3 > 100 { print $0 }' data.txt
# 第一列等于 "admin"
awk '$1 == "admin" { print $0 }' users.txt
复合模式
复合模式是通过逻辑运算符(&&
、||
、!
)组合多个条件来创建更复杂的匹配规则。
# 第一列是 "error" 且第四列大于 100
awk '$1 == "error" && $4 > 100 { print $0 }' log.txt
# 第二列小于 50 或大于 100
awk '$2 < 50 || $2 > 100 { print $0 }' data.txt
特殊模式
# BEGIN:在处理第一行之前执行
# END:在处理完最后一行后执行
awk '
BEGIN { print "Start processing" }
{ print $0 }
END { print "End processing" }
' file.txt
动作的常见用途
打印操作
# 直接打印整行
{ print $0 }
# 打印特定字段
{ print $1, $3 }
# 格式化打印
{ printf "Name: %s, Age: %d\n", $1, $2 }
计算操作
# 累加第一列的值
{ sum += $1 }
END { print "总和:", sum }
# 计算平均值
{
total += $1
count++
}
END {
print "平均值:", total/count
}
条件处理
# 如果第二列大于60,打印"及格"
{
if ($2 > 60) {
print "及格"
} else {
print "不及格"
}
}
使用示例
# 打印特定列
awk '{print $1, $3}' file.txt
# 使用自定义分隔符
awk -F: '{print $1}' /etc/passwd
# 条件过滤
awk '$3 > 100 {print $0}' data.txt
# 计算总和
awk '{sum += $1} END {print sum}' numbers.txt
# 统计行数
awk 'END {print NR}' file.txt
# 复杂处理示例
awk '
BEGIN {
print "开始处理..."
sum = 0
}
$1 > 0 {
sum += $1
count++
}
END {
printf "平均值: %.2f\n", sum/count
}
' data.txt
实用组合示例
grep
、sed
、awk
命令经常结合使用,能够实现更强大的文本处理功能:
# 查找并替换
grep "pattern" file.txt | sed 's/old/new/g'
# 过滤并统计
grep "error" log.txt | awk '{count[$3]++} END {for(i in count) print i, count[i]}'
# 复杂日志分析
awk '/ERROR/ {print $0}' log.txt | sed 's/ERROR/严重错误/g' | grep "2024"
总结
- grep适合文本搜索和过滤
- sed适合文本替换和编辑
- awk适合复杂的文本处理和数据分析
这三个命令各有特色,组合使用可以解决绝大多数文本处理需求。