grep是行筛选器,只输出整行且不修改原内容;关键词须用引号包裹以防shell解析错误;含特殊字符需加-f或转义;-i忽略大小写;-v作用于整行;-o提取匹配子串但与-n、-w互斥;-r递归时应排除干扰并优先用-f提升性能。

直接说结论:grep 不是“过滤器”而是“行筛选器”——它只输出整行,不删改原内容;所谓“过滤”,本质是按条件保留或排除整行。
grep 怎么匹配关键词(含大小写、空格、特殊字符)
关键词必须用引号包裹,否则 shell 会先解析空格或 *、$ 等字符,导致命令失败或语义错乱。
- 含空格的词:用双引号或单引号,如
grep "failed login" /var/log/auth.log - 含
.、^、$等正则元字符:若只想当普通字符搜,加-F或用fgrep,如grep -F "192.168.1.1" access.log - 大小写敏感是默认行为;要忽略大小写,必须加
-i,如grep -i "error" syslog,否则"Error"不会命中
grep -v 怎么正确反向过滤(常见误用)
-v 是“排除匹配行”,不是“排除关键词本身”。它作用于整行,且容易和管道、多条件混淆。
- 错误写法:
grep "nginx" config.conf | grep -v "#"—— 这会先筛出含 nginx 的行,再从中剔除带#的行,但可能漏掉注释行里隐含的配置逻辑 - 正确思路:若想“排除注释和空行,再找 nginx”,应分步:
grep -v "^#" config.conf | grep -v "^$" | grep "nginx" - 注意
^#中的^表示行首,必须用引号包裹,否则^被 shell 解析为历史命令调用
grep 怎么只显示匹配部分(不是整行)
默认输出整行,但有时你只需要提取 IP、端口号、日志级别等片段——这时要用 -o,但它有严格限制:
-
-o必须配合正则使用,且只输出“连续匹配的子串”,不会跨空格或换行;例如grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" log.txt可抽 IPv4 - 不能和
-w同时用:grep -ow "port"会报错,因为-o和-w冲突(一个切片段,一个保单词边界) - 想同时显示行号?不行。
-o和-n互斥——-o输出的是子串位置,-n是行号,grep 不提供“子串行内偏移”功能
grep 递归搜索时怎么避免报错和性能陷阱
grep -r 看似方便,但实际中常因权限、二进制文件、符号链接崩出一堆 warning,甚至卡死。
- 加
--exclude-dir=".git"或--exclude="*.log"排除干扰目录/文件,避免搜千兆日志 - 遇到
Binary file xxx matches提示?加-a强制文本解析,或更稳妥地用--binary-files=without-match - 不要对整个
/或/usr直接-r;先find . -name "*.conf" -print0 | xargs -0 grep "timeout"更可控 - 想快速搜固定字符串(非正则)?用
grep -F -r,比默认模式快 3–5 倍,尤其在大文件中
真正难的不是语法,而是判断“该不该用 grep”:它不修改文件、不排序、不去重、不结构化解析。一行日志里有时间戳+IP+状态码,你要按状态码统计?别硬套 grep | wc -l,该上 awk '{print $9}' | sort | uniq -c 了。











