6.Shell脚本修炼手册---grep命令使用指南

grep 命令:从文本中精准筛选信息的实用指南

文章目录

  • [grep 命令:从文本中精准筛选信息的实用指南](#grep 命令:从文本中精准筛选信息的实用指南)
    • [一、什么是 grep?为什么要用它?](#一、什么是 grep?为什么要用它?)
    • [二、grep 基本语法](#二、grep 基本语法)
    • 三、常用选项详解(附实例)
      • [(一)模式选择:怎么定义 "要找的内容"?](#(一)模式选择:怎么定义 “要找的内容”?)
        • [1. `-E`:支持复杂的匹配规则(扩展正则表达式)](#1. -E:支持复杂的匹配规则(扩展正则表达式))
        • [2. `-e`:一次匹配多个模式](#2. -e:一次匹配多个模式)
        • [3. `-f`:从文件中读取匹配模式](#3. -f:从文件中读取匹配模式)
        • [4. `-i`:忽略大小写](#4. -i:忽略大小写)
        • [5. `-w`:只匹配完整单词](#5. -w:只匹配完整单词)
        • [6. `-x`:只匹配完整的行](#6. -x:只匹配完整的行)
      • (二)输出控制:怎么展示筛选结果?
        • [1. `-v`:反向匹配(显示不包含模式的行)](#1. -v:反向匹配(显示不包含模式的行))
        • [2. `-m`:限制最大匹配数量](#2. -m:限制最大匹配数量)
        • [3. `-c`:统计匹配到的行数](#3. -c:统计匹配到的行数)
        • [4. `-n`:显示匹配行的行号](#4. -n:显示匹配行的行号)
        • [5. `-o`:只显示匹配到的部分(不显示整行)](#5. -o:只显示匹配到的部分(不显示整行))
        • [6. `-q`:静默模式(只判断是否存在,不输出内容)](#6. -q:静默模式(只判断是否存在,不输出内容))
      • (三)查找文件:如何在目录中递归搜索?
        • [1. `-r` / `-R`:递归搜索目录](#1. -r / -R:递归搜索目录)
        • [2. `-h` / `-H`:控制是否显示文件名](#2. -h / -H:控制是否显示文件名)
        • [3. `-l` / `-L`:只显示包含 / 不包含模式的文件名](#3. -l / -L:只显示包含 / 不包含模式的文件名)
      • (四)上下文控制:显示匹配行的前后内容
        • [1. `-B`:显示匹配行和前面的行](#1. -B:显示匹配行和前面的行)
        • [2. `-A`:显示匹配行和后面的行](#2. -A:显示匹配行和后面的行)
        • [3. `-C`:显示匹配行和前后的行](#3. -C:显示匹配行和前后的行)
    • 四、总结

一、什么是 grep?为什么要用它?

在 Linux 系统中,我们经常需要从大量文本中快速找到包含特定内容的行 ------ 比如从日志文件中找错误信息、从配置文件中找关键参数。grep 就是专门干这件事的工具,它能像 "文本侦探" 一样,从文件或命令输出中精准筛选出符合条件的内容。

Linux 处理文本有 "三剑客":grep 擅长 "筛选",sed 擅长 "修改",awk 擅长 "格式化输出"。掌握 grep,能让你在处理文本时效率翻倍。

二、grep 基本语法

grep 的使用场景主要有两种,语法对应如下:

  1. 从命令输出中筛选 (通过管道 | 传递数据):

    bash 复制代码
    其他命令 | grep [选项] 匹配模式

    例:[bq@shell bin]$ ls -l | grep 'txt'(从 ls 输出中找包含 txt 的行)

  2. 从文件中筛选

    bash 复制代码
    grep [选项] 匹配模式 文件名

    例:[bq@shell bin]$ grep 'error' app.log(从 app.log 中找包含 error 的行)

三、常用选项详解(附实例)

(一)模式选择:怎么定义 "要找的内容"?

这部分选项用来控制 "匹配规则",让 grep 知道你想找什么样的内容。

1. -E:支持复杂的匹配规则(扩展正则表达式)

理论 :默认情况下,grep 只支持简单的正则表达式(比如 * ?),加上 -E 后可以用更复杂的规则(比如 {n} 表示重复次数、| 表示 "或"),相当于 egrep 命令。

示例 :找连续出现 3 次 dog 的行

bash 复制代码
# 从 words 文件中找包含 "dogdogdog" 的行
[bq@shell bin]$ cat words | grep -E '(dog){3}'  # (dog){3} 表示 "dog" 连续出现 3 次
# 输出:
# dogdogdog
# dogdogdogdog
2. -e:一次匹配多个模式

理论 :当你想同时找多个关键词时,用 -e 可以指定多个匹配模式(相当于 "或" 的关系)。

示例 :同时找包含 catdog 的行

bash 复制代码
[bq@shell bin]$ cat words | grep -e 'cat' -e 'dog'  # -e 后面跟第一个模式,再用一个 -e 跟第二个模式
# 输出:
# cat
# category
# acat
# concatenate
# dog
# dogdog
# ...(所有含 cat 或 dog 的行)
3. -f:从文件中读取匹配模式

理论 :如果要匹配的模式太多(比如几十上百个关键词),逐个用 -e 写太麻烦,这时可以把模式存到文件里,用 -fgrep 从文件读。

实验流程

① 创建一个存模式的文件(每行一个模式);

② 用 grep -f 读取该文件,筛选包含任一模式的行。

示例

bash 复制代码
# 步骤1:创建模式文件,包含 "cat" 和 "dog"
[bq@shell bin]$ echo -e 'cat\ndog' > patterns.txt  # 用 echo -e 换行,将内容写入 patterns.txt

# 步骤2:查看模式文件内容
[bq@shell bin]$ cat patterns.txt
# 输出:
# cat
# dog

# 步骤3:从 words 中筛选包含 patterns.txt 中任一模式的行
[bq@shell bin]$ cat words | grep -f patterns.txt  # -f 后面跟存模式的文件
# 输出和 -e 'cat' -e 'dog' 相同,因为模式文件里就是这两个词
4. -i:忽略大小写

理论 :默认情况下,grep 区分大小写(比如 Catcat 会被当成不同内容),-i 可以关闭大小写区分。

示例 :找包含 cBt(不区分大小写)的行

bash 复制代码
[bq@shell bin]$ cat words | grep -i 'cBt'  # -i 让匹配时忽略大小写,所以能匹配到 "cbt"
# 输出:
# cbt
5. -w:只匹配完整单词

理论 :默认情况下,grep 'cat' 会匹配包含 cat 的所有内容(比如 category 里的 cat),-w 只匹配 "完整单词"(前后是空格、标点或开头 / 结尾)。

示例 :只找单独的 cat 单词

bash 复制代码
[bq@shell bin]$ cat words | grep -w 'cat'  # 只匹配 "cat" 这个完整单词,不匹配 "category" 里的 "cat"
# 输出:
# cat
# hello cat  # 这里 "cat" 是单独的词
6. -x:只匹配完整的行

理论 :如果想找 "整行内容完全等于某个模式" 的行(而不是包含该模式),用 -x

示例 :只找内容正好是 cat 的行

bash 复制代码
[bq@shell bin]$ cat words | grep -x 'cat'  # 只有当一行内容完全是 "cat" 时才会被匹配
# 输出:
# cat  # 其他行比如 "category" 因为内容不全是 "cat",所以不匹配

(二)输出控制:怎么展示筛选结果?

这部分选项用来控制筛选结果的展示形式,比如只看数量、隐藏文件名等。

1. -v:反向匹配(显示不包含模式的行)

理论 :默认是显示 "包含模式" 的行,-v 反过来,显示 "不包含模式" 的行(相当于 "排除")。

示例 1 :排除以 dc 开头的行

bash 复制代码
[bq@shell bin]$ cat words | grep -v '^d|^c'  # ^d 表示以 d 开头,^c 表示以 c 开头,-v 排除这些行
# 输出:
# acat  # 不以 d 或 c 开头
# hello cat

示例 2:过滤配置文件中的注释和空行

bash 复制代码
[bq@shell bin]$ grep -v '^ *#|^$' /etc/profile  # ^ *# 表示以任意空格+#开头(注释行),^$ 表示空行,-v 排除它们
# 输出:/etc/profile 中有效的配置行(非注释、非空)
2. -m:限制最大匹配数量

理论 :当匹配到的行太多时,用 -m 数字 可以让 grep 找到指定数量的行后就停止。

示例 :只显示前 2 个包含 dog 的行

bash 复制代码
# 先看所有包含 dog 的行
[bq@shell bin]$ cat words | grep 'dog'
# 输出:
# dog
# dogdog
# dogdogdog
# dogdogdogdog

# 只显示前 2 行
[bq@shell bin]$ cat words | grep -m2 'dog'  # -m2 表示最多匹配 2 行
# 输出:
# dog
# dogdog
3. -c:统计匹配到的行数

理论 :不想看具体内容,只想知道有多少行符合条件,用 -c 直接输出数量。

示例 :统计包含 dog 的行数

bash 复制代码
[bq@shell bin]$ cat words | grep -c 'dog'  # -c 计算匹配到的行数
# 输出:4 (因为有 4 行包含 dog)
4. -n:显示匹配行的行号

理论 :需要知道匹配内容在文件中的位置时,-n 会在每行前加上行号。

示例 :显示包含 cat 的行及其行号

bash 复制代码
[bq@shell bin]$ cat words | grep -n 'cat'  # -n 显示行号(格式:行号:内容)
# 输出:
# 1:cat  # 第 1 行
# 2:category  # 第 2 行
# 3:acat  # 第 3 行
# ...
5. -o:只显示匹配到的部分(不显示整行)

理论 :默认会显示整行内容,-o 只提取行中与模式匹配的部分(适合提取具体关键词)。

示例 :只提取连续 3 次 dog 的部分

bash 复制代码
# 先看包含 "dogdogdog" 的整行
[bq@shell bin]$ cat words | grep -E '(dog){3}'
# 输出:
# dogdogdog
# dogdogdogdog

# 只提取匹配的部分
[bq@shell bin]$ cat words | grep -E -o '(dog){3}'  # -o 只显示匹配到的 "dogdogdog"
# 输出:
# dogdogdog
# dogdogdog  # 第二行中的前 3 个 dog 被提取出来
6. -q:静默模式(只判断是否存在,不输出内容)

理论 :在脚本中常用,-qgrep 不显示任何结果,但可以通过系统变量 $? 判断是否匹配到(0 表示匹配到,1 表示没匹配到)。

示例 :判断是否存在连续 3 次 dog 的行

bash 复制代码
# 情况1:存在匹配内容
[bq@shell bin]$ cat words | grep -q -E '(dog){3}'  # -q 不输出内容
[bq@shell bin]$ echo $?  # $? 是上一条命令的返回值,0 表示成功(匹配到)
# 输出:0

# 情况2:不存在匹配内容
[bq@shell bin]$ cat words | grep -q -E '(dog){3}abc'  # 找 "dogdogdogabc",不存在
[bq@shell bin]$ echo $?
# 输出:1

(三)查找文件:如何在目录中递归搜索?

当需要在多个文件或目录中查找时,这些选项能帮你高效遍历。

1. -r / -R:递归搜索目录

理论

  • -r:递归搜索目录下的所有文件(不跟随软链接);
  • -R:递归搜索,且会跟随软链接(类似访问真实文件)。

示例 :在 /etc 目录中找包含 SELINUX= 的行

bash 复制代码
[bq@shell bin]$ grep -r '^SELINUX=' -s /etc  # -r 递归搜索 /etc,-s 不显示权限不足的错误,^SELINUX= 匹配以 SELINUX= 开头的行
# 输出:
# /etc/selinux/config:SELINUX=disabled  # 找到的结果
2. -h / -H:控制是否显示文件名

理论

  • -h:只显示匹配的内容,不显示文件名;
  • -H:显示内容时附带文件名(默认行为)。

示例

bash 复制代码
# 不显示文件名
[bq@shell bin]$ grep -r '^SELINUX=' -s -h /etc  # -h 隐藏文件名
# 输出:SELINUX=disabled

# 显示文件名(默认)
[bq@shell bin]$ grep -r '^SELINUX=' -s -H /etc  # -H 显式指定显示文件名
# 输出:/etc/selinux/config:SELINUX=disabled
3. -l / -L:只显示包含 / 不包含模式的文件名

理论

  • -l:只输出 "包含匹配内容" 的文件名;
  • -L:只输出 "不包含匹配内容" 的文件名。

示例

bash 复制代码
# 只显示包含 SELINUX= 的文件
[bq@shell bin]$ grep -r '^SELINUX=' -s -l /etc  # -l 只输出文件名
# 输出:/etc/selinux/config

# 只显示不包含 SELINUX= 的文件(最后5个)
[bq@shell bin]$ grep -r '^SELINUX=' -s -L /etc | tail -5  # -L 输出不包含的文件,tail -5 取最后5个
# 输出:
# /etc/gdm/PostLogin/Default.sample
# /etc/gdm/PostSession/Default
# ...(其他不包含的文件)

(四)上下文控制:显示匹配行的前后内容

当需要查看匹配内容的 "上下文"(前后几行)时,用这些选项。

1. -B:显示匹配行和前面的行

理论-B 数字 表示显示匹配行及其前面 数字 行的内容(B = Before)。

示例 :显示包含 10.1.8.88 的行及其前面 2 行

bash 复制代码
[bq@shell bin]$ ip addr | grep '10.1.8.88' -B2  # -B2 显示匹配行和前面 2 行
# 输出:
# 2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...  # 前2行
#     link/ether 00:0c:29:2b:c8:7a brd ...  # 前1行
#     inet 10.1.8.88/24 brd ...  # 匹配行
2. -A:显示匹配行和后面的行

理论-A 数字 表示显示匹配行及其后面 数字 行的内容(A = After)。

示例 :显示包含 ens32: 的行及其后面 2 行

bash 复制代码
[bq@shell bin]$ ip addr | grep 'ens32:' -A2  # -A2 显示匹配行和后面 2 行
# 输出:
# 2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu ...  # 匹配行
#     link/ether 00:0c:29:2b:c8:7a brd ...  # 后1行
#     inet 10.1.8.88/24 brd ...  # 后2行
3. -C:显示匹配行和前后的行

理论-C 数字 表示显示匹配行及其前后各 数字 行的内容(C = Context)。

示例 :显示包含 10.1.8.88 的行及其前后各 2 行

bash 复制代码
[bq@shell bin]$ ip addr | grep '10.1.8.88' -C2  # -C2 显示匹配行和前后各 2 行
# 输出:
# 2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu ...  # 前2行
#     link/ether 00:0c:29:2b:c8:7a brd ...  # 前1行
#     inet 10.1.8.88/24 brd ...  # 匹配行
#        valid_lft forever preferred_lft forever  # 后1行
#     inet6 fe80::5882:62aa:161b:c9c1/64 ...  # 后2行

四、总结

grep 的核心是 "筛选",通过不同选项可以灵活控制匹配规则、输出形式和搜索范围。记住几个高频选项能解决大部分问题:

  • 忽略大小写:-i
  • 反向匹配:-v
  • 显示行号:-n
  • 递归搜索:-r
  • 上下文查看:-B / -A / -C

如涉及版权问题,请联系作者处理!!!!!