Skip to content

grep

字数: 2070 字 时长: 8 分钟

grep 是一个强大的文本搜索工具,用于在文件或文本流中查找符合特定模式(通常是正则表达式)的行,并将这些行输出。grep 的名称源自 Global Regular Expression Print(全局正则表达式打印)的缩写。

grep 的核心功能是在一个或多个文件中搜索指定的字符串模板(模式),并将匹配的行输出到屏幕(标准输出)。grep 可用于 shell 脚本,因为 grep 通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回 0,如果搜索不成功,则返回 1,如果搜索的文件不存在,则返回 2。利用这些返回值就可进行一些自动化的文本处理工作。

基本语法

grep 的基本语法如下:

shell
grep [OPTION...] PATTERNS [FILE...]
  • PATTERNS:模式,表示要搜索的字符串或正则表达式。
  • FILE:要搜索的文件(可以是一个或多个文件,如果未指定文件,则从标准输入读取)。

grep 提供了丰富的选项来满足不同的搜索需求。以下是一些常用选项:

搜索控制作用
-i忽略大小写。
-v反向匹配,显示不包含模式的行。
-w匹配整个单词。
-x匹配整行。
上下文控制作用
-A <n>显示匹配行及其后 n 行
-B <n>显示匹配行及其前 n 行。
-C <n>显示匹配行及其前后各 n 行。
输出控制作用
-n显示匹配行的行号。
-c统计匹配行的数量。
-o只输出匹配的部分,而不是整行。
-q静默模式,不输出任何内容,仅通过返回值表示是否匹配成功(常用于脚本中)。
-s会禁止错误消息的输出。这意味着,如果使用此选项运行 grep,并且发生错误(例如,文件不存在),则不会在终端中显示错误消息。
文件控制作用
-r-R递归搜索目录中的文件。但 -R 会遵循所有符号链接。
--include指定要搜索的文件类型。
--exclude排除特定文件类型。

grep 支持基本正则表达式(BRE)和扩展正则表达式(ERE)。可以通过 -E 选项启用扩展正则表达式。下是一些常见的正则表达式元字符及其功能:

元字符功能示例示例的匹配对象
^行首定位符^love匹配所有以 love 开头的行
$行尾定位符love$ 匹配所有以 love 结尾的行
.匹配除换行外的单个字符l..e匹配包含字符 l、后跟两个任意字符、再跟字母 e 的行
*匹配零个或多个前导字符*love匹配在零个或多个空格紧跟着模式 love 的行
[]匹配指定字符组内任一字符[Ll]ove匹配包含 love 和 Love 的行
[^]匹配不在指定字符组内的任一字符[^Ll]ove匹配不以 L 或 l 开头,但后面跟 ove 的行
?匹配零个或一个前导字符colou?r匹配 color 或 colour
+匹配一个或多个前导字符lo+ve匹配 love,但不匹配 lve
{n,m}匹配前导字符出现的次数范围lo{2,4}ve匹配 loove、loooove 等,但不匹配 love 或 loooooove
|逻辑或love|like匹配 love 或 like
\转义字符\.匹配字面意义上的 .,而不是任意字符
()分组(love|like) you匹配 love you 或 like you

匹配条件

  1. 搜索指定文件中包含某个关键词的内容行

    在 /etc/passwd 文件中查找包含 root 的行:

    shell
    [root@localhost ~]# grep root /etc/passwd
    root:x:0:0:root:/root:/bin/shell
    operator:x:11:0:operator:/root:/sbin/nologin
  2. 搜索多个文件中包含某个关键词的内容行

    在 /etc/passwd 和 /etc/shadow 文件中查找包含 root 的行:

    shell
    [root@localhost ~]# grep root /etc/passwd /etc/shadow
    /etc/passwd:root:x:0:0:root:/root:/bin/shell
    /etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
    /etc/shadow:root:$6$9dGlhMoEUng5lWby$RFSTfWO5GH/Cen49s9.5I7sXkGC5jA0R76e9VDHX.1psMU/biK0olqti/np3vvwkEGq9e0Zu7qQmsnzMoo3p30::0:99999:7:::
  3. 忽略大小写搜索

    在 /etc/shadow 文件中查找包含 Ff 的行(忽略大小写):

    shell
    [root@localhost ~]# grep -i F /etc/shadow
    root:$6$9dGlhMoEUng5lWby$RFSTfWO5GH/Cen49s9.5I7sXkGC5jA0R76e9VDHX.1psMU/biK0olqti/np3vvwkEGq9e0Zu7qQmsnzMoo3p30::0:99999:7:::
    ftp:*:19820:0:99999:7:::
  4. 查看匹配行的上下文

    在 /etc/passwd 文件中查找包含 ftp 的行,并显示匹配行及其前后各 1 行:

    shell
    [root@localhost ~]# grep -1 ftp /etc/passwd
    games:x:12:100:games:/usr/games:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
  5. 取反匹配

    在 /etc/passwd 文件中查找不包含 nologin 的行:

    shell
    [root@localhost ~]# grep -v nologin /etc/passwd
    root:x:0:0:root:/root:/bin/shell
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
  6. 显示匹配行的文件名

    在 /etc/passwd 和 /etc/shadow 文件中查找包含 root 的行,并显示文件名:

    shell
    [root@localhost ~]# grep -H root /etc/passwd /etc/shadow
    /etc/passwd:root:x:0:0:root:/root:/bin/shell
    /etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
    /etc/shadow:root:$6$9dGlhMoEUng5lWby$RFSTfWO5GH/Cen49s9.5I7sXkGC5jA0R76e9VDHX.1psMU/biK0olqti/np3vvwkEGq9e0Zu7qQmsnzMoo3p30::0:99999:7:::
  7. 统计匹配行的数量

    统计 /etc/passwd 和 /etc/shadow 文件中包含 root 的行数:

    shell
    [root@localhost ~]# grep -c root /etc/passwd /etc/shadow
    /etc/passwd:2
    /etc/shadow:1
  8. 递归搜索目录及其子目录

    在 /etc/ 目录及其子目录下的所有文件中查找包含 root 的文件名:

    shell
    [root@localhost ~]# grep -lr root /etc/
    /etc/aliases
    /etc/anacrontab
    /etc/audit/auditd.conf
    /etc/chrony.keys
    /etc/cron.d/0hourly
    /etc/crontab
    ……

    注意,如果没有加选项 -r 不会递归搜索子目录,遇到目录的话会提示 Is a directory

正则匹配

  1. 搜索以某个字符串开头的行

    在 /etc/selinux/config 文件中查找以 SELINUX 开头的行:

    shell
    [root@localhost ~]# grep ^SELINUX /etc/selinux/config
    SELINUX=enforcing
    SELINUXTYPE=targeted
  2. 搜索以某个字符串结尾的行

    在 /etc/selinux/config 文件中查找以 SELINUX 结尾的行:

    shell
    [root@localhost ~]# grep SELINUX$ /etc/selinux/config

    这里没有找到就没有输出。

  3. 同时匹配多个条件

    在 /etc/selinux/config 文件中查找包含 enforcingpermissivedisabled 的行:

    shell
    [root@localhost ~]# grep -E "enforcing|permissive|disabled" /etc/selinux/config
    #     enforcing - SELinux security policy is enforced.
    #     permissive - SELinux prints warnings instead of enforcing.
    #     disabled - No SELinux policy is loaded.
    # NOTE: Up to RHEL 8 release included, SELINUX=disabled would also
    # fully disabled instead of SELinux running with no policy loaded, you
    SELINUX=enforcing
  4. 过滤空行和注释行

    在 /etc/selinux/config 文件中查找非空行且非注释行(即不以 # 开头且不为空的行):

    shell
    [root@localhost ~]# grep -Ev "^#|^$" /etc/selinux/config
    SELINUX=enforcing
    SELINUXTYPE=targeted

其他常用组合

  1. 显示匹配行的行号

    在 /etc/passwd 文件中查找包含 root 的行,并显示行号:

    shell
    [root@localhost ~]# grep -n root /etc/passwd
    1:root:x:0:0:root:/root:/bin/shell
    10:operator:x:11:0:operator:/root:/sbin/nologin
  2. 只输出匹配的部分

    在 /etc/passwd 文件中查找 root,并只输出匹配的部分(而不是整行):

    shell
    [root@localhost ~]# grep -o root /etc/passwd
    root
    root
    root
    root
  3. 从文件中读取模式

    shell
    error
    warning
    critical
    shell
    This is an error message.
    This is a warning message.
    This is a normal message.
    This is a critical error.

    使用 -f 选项,grep 会逐行读取 patterns.txt 中的模式,并在 file.txt 中查找包含这些模式的行。如果某一行包含 patterns.txt 中的任意一个模式,这一行就会被匹配并输出:

    shell
    [root@localhost ~]# grep -f patterns.txt file.txt
    This is an error message.
    This is a warning message.
    This is a critical error.

    如果有多个模式需要搜索,手动在命令行中输入这些模式会非常麻烦。将这些模式保存到一个文件中,可以更方便地管理和复用。并且如果搜索模式需要频繁更新,只需修改 patterns.txt 文件,而不需要修改命令。

  4. 结合管道使用

    从 /var/log/messages 文件中查找包含 error 的行(忽略大小写):

    shell
    [root@localhost ~]# cat /var/log/messages | grep -i error
    ……
    Jan 15 08:18:43 localhost irqbalance[714]: Cannot change IRQ 73 affinity: Input/output error
    Jan 15 08:18:43 localhost irqbalance[714]: Cannot change IRQ 63 affinity: Input/output error

高级用法

在 /var/log 目录及其子目录下的所有文件中查找包含 ERROR 的行,但排除 .log 文件:

shell
[root@localhost ~]# grep -r --exclude="*.log" ERROR /var/log
/var/log/anaconda/syslog:08:43:45,471 WARNING org.fedoraproject.Anaconda.Modules.Storage:ERROR:blivet:edd: unable to match edd entry 0x80