文本搜索:grep
grep 核心定位
grep(Global Regular Expression Print)是 Linux 文本搜索的核心工具,基于正则表达式匹配,配合管道 | 可以处理任意命令的输出。
基础用法
# 在文件中搜索包含 "error" 的行
grep "error" log.txt
# 忽略大小写(-i ignore-case)
grep -i "error" log.txt
# 显示行号(-n line-number)
grep -n "error" log.txt
# 显示不匹配的行(-v invert-match)
grep -v "error" log.txt
# 只显示匹配的文件名(-l files-with-matches)
grep -l "error" *.log
# 显示匹配次数(-c count)
grep -c "error" log.txt
# 显示匹配上下文(-C context)
grep -C 2 "error" log.txt # 显示匹配行及前后 2 行
正则表达式基础
基本正则(BRE,默认)
| 元字符 | 含义 | 示例 |
|---|---|---|
. | 任意单个字符 | g.p 匹配 gap, gbp, gcp |
* | 前一个字符 0 次或多次 | go*d 匹配 gd, god, good |
^ | 行首 | ^error 匹配行首的 error |
$ | 行尾 | error$ 匹配行尾的 error |
[] | 字符类 | [aeiou] 匹配任意元音 |
[^] | 反向字符类 | [^0-9] 匹配非数字 |
扩展正则(ERE,-E)
# 使用扩展正则(-E extended-regexp)
grep -E "go+d" file.txt # + 表示 1 次或多次
grep -E "go?d" file.txt # ? 表示 0 次或 1 次
grep -E "good|bad" file.txt # | 表示或
grep -E "(go)+" file.txt # () 分组
| 元字符 | 含义 | 示例 |
|---|---|---|
+ | 1 次或多次 | go+d 匹配 god, good |
? | 0 次或 1 次 | go?d 匹配 gd, god |
| ` | ` | 或 |
() | 分组 | (ab)+ 匹配 ab, abab |
{n} | 恰好 n 次 | a{3} 匹配 aaa |
{n,} | 至少 n 次 | a{2,} 匹配 aa, aaa |
{n,m} | n 到 m 次 | a{1,3} 匹配 a, aa, aaa |
实用选项组合
# 递归搜索目录(-r recursive)
grep -r "error" /var/log/
# 递归搜索并显示文件名(-H with-filename)
grep -rH "error" /var/log/
# 递归搜索,排除二进制文件(-I ignore-binary)
grep -rI "error" /var/log/
# 搜索时排除特定文件(--exclude)
grep -r "error" /var/log/ --exclude="*.gz"
# 搜索时排除特定目录(--exclude-dir)
grep -r "error" /var/log/ --exclude-dir="archive"
# 只匹配整个单词(-w word-regexp)
grep -w "error" file.txt # 匹配 "error" 但不匹配 "errors"
# 只匹配整行(-x line-regexp)
grep -x "error" file.txt # 只匹配单独一行的 "error"
# 限制匹配数量(-m max-count)
grep -m 5 "error" file.txt # 只显示前 5 个匹配
# 静默模式(-q quiet),用于脚本判断
if grep -q "error" log.txt; then
echo "发现错误"
fi
管道组合实战
场景 1:查找日志中的错误并统计
# 查找包含 ERROR 的行
grep "ERROR" app.log
# 统计 ERROR 出现次数
grep -c "ERROR" app.log
# 查找 ERROR 并显示前后 3 行上下文
grep -C 3 "ERROR" app.log
# 查找所有日志文件中的 ERROR
grep -r "ERROR" /var/log/
场景 2:过滤进程列表
# 查找 nginx 进程
ps aux | grep nginx
# 排除 grep 自身(grep [n]ginx 技巧)
ps aux | grep [n]ginx
# 或更优雅的方式
ps aux | grep nginx | grep -v grep
场景 3:查找代码中的函数定义
# 查找 C 语言中的 main 函数定义
grep -n "^int main" *.c
# 查找 Python 中的函数定义
grep -n "^def " *.py
# 查找包含 TODO 或 FIXME 的注释
grep -rn "TODO\|FIXME" src/
grep 家族
| 命令 | 特点 | 适用场景 |
|---|---|---|
grep | 基本正则 | 通用搜索 |
egrep | 扩展正则(等同于 grep -E) | 复杂正则 |
fgrep | 固定字符串(等同于 grep -F) | 搜索含特殊字符的字符串 |
rg (ripgrep) | 极速递归搜索 | 大型代码库搜索 |
ag (The Silver Searcher) | 快速搜索,自动忽略版本控制 | 代码搜索 |
# ripgrep 示例(需安装)
rg "error" /var/log/ # 递归搜索,自动忽略隐藏文件
rg -t py "def main" # 只在 Python 文件中搜索
rg -C 3 "error" app.log # 显示上下文
本篇小结
grep "pattern" file:基础文本搜索,基于正则表达式-i忽略大小写,-n显示行号,-v反向匹配,-c计数-r递归搜索目录,--exclude排除文件,--exclude-dir排除目录-w匹配整个单词,-x匹配整行,-q静默模式(脚本判断)- 基本正则:
.*^$[];扩展正则(-E):+?|(){n,m} - 管道组合:
ps aux | grep nginx | grep -v grep egrep=grep -E,fgrep=grep -F,rg是现代化替代
动手实践
基础搜索练习:
# 创建一个测试文件 cat > test.txt apple banana Application apply pine pineapple # Ctrl+D grep "app" test.txt grep -i "app" test.txt grep -n "app" test.txt grep -w "app" test.txt grep -v "app" test.txt正则表达式练习:
grep "^a" test.txt # 以 a 开头 grep "e$" test.txt # 以 e 结尾 grep "a.e" test.txt # a 和 e 中间一个字符 grep -E "a+p" test.txt # 1 个或多个 a 后跟 p进程过滤练习:
ps aux | grep bash ps aux | grep [b]ash # 排除 grep 自身递归搜索练习:
grep -r "TODO" /usr/share/doc/ --exclude-dir=".git"统计练习:
grep -c "error" /var/log/syslog grep -r -c "error" /var/log/思考:为什么
ps aux | grep nginx | grep -v grep能排除 grep 自身?如果写成ps aux | grep -v grep | grep nginx,结果会有什么不同?