如何使用Grep命令在Linux中搜索文件

grep命令代表“全局正则表达式打印”,是Linux中最强大和最常用的命令之一。

Grep在一个或多个输入文件中搜索与给定模式匹配的行,并将每个匹配行写入标准输出。如果没有指定文件,则grep从标准输入读取,标准输入通常是另一个命令的输出。

在本教程中,我们将通过实际示例和最常见的GNU grep选项的详细说明向您展示如何使用grep命令。

Grep命令语法

在讨论如何使用Grep命令之前,让我们先回顾一下基本语法。

Grep实用程序表达式采用以下形式:

grep [OPTIONS] PATTERN [FILE...]

方括号中的项目是可选的。

  • OPTIONS - 零个或多个选项。Grep提供了许多控制其行为的选项
  • PATTERN - 搜索模式。
  • FILE - 零个或多个输入文件名。

如何使用Grep在文件中搜索字符串

grep命令的最基本用法是在文件中搜索字符串(文本)。

例如,要显示/etc/passwd包含该字符串的文件中的行,bash可以使用以下命令:

grep bash /etc/passwd

输出应该如下所示:

root❌0:0:root:/root:/bin/bash
linuxize❌1000:1000:linuxize:/home/linuxize:/bin/bash

如果字符串包含空格,则需要用单引号或双引号将其括起来:

grep "Gnome Display Manager" /etc/passwd

Grep反转匹配(排除)

要显示与模式不匹配的行,请使用-v(或--invert-match)选项。

例如,要显示/etc/passwd文件中不包含字符串的行nologin,可以使用以下命令:

grep -v nologin /etc/passwd
root❌0:0:root:/root:/bin/bash
colord❌124:124::/var/lib/colord:/bin/false
git❌994:994:git daemon user:/:/usr/bin/git-shell
linuxize❌1000:1000:linuxize:/home/linuxize:/bin/bash

如何使用Grep在命令输出中搜索字符串

相反,如果指定输入文件,则可以将另一个命令的输出传递给grep,然后仅显示与给定模式匹配的行。

例如,要查找作为用户在系统上运行的进程,www-data可以使用以下命令:

ps -ef | grep www-data
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
root     18272 17714  0 16:00 pts/0    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
www-data 31147 12770  0 Oct22 ?        00:05:51 nginx: worker process
www-data 31148 12770  0 Oct22 ?        00:00:00 nginx: cache manager process

您还可以在命令中链接多个管道。正如您在上面的输出中看到的那样,还有一行包含grep进程。如果您不希望显示该行,则将输出传递给另一个grep实例,如下所示。

ps -ef | grep www-data | grep -v grep
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
root     18272 17714  0 16:00 pts/0    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
www-data 31147 12770  0 Oct22 ?        00:05:51 nginx: worker process
www-data 31148 12770  0 Oct22 ?        00:00:00 nginx: cache manager process

Grep递归搜索

要递归搜索模式,请使用-r选项(或--recursive)。这将搜索指定目录中的所有文件,跳过递归遇到的符号链接。要关注所有符号链接,请使用-R选项(或--dereference-recursive)。

在以下示例中,我们将在目录linuxize.com中的所有文件中搜索字符串/etc

grep -r linuxize.com /etc

该命令将打印以文件的完整路径为前缀的匹配行。

/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;

如果-r您使用-R选项grep将遵循所有符号链接:

grep -R linuxize.com /etc

注意输出的最后一行。上面的示例中未打印该行,因为Nginx sites-enabled目录中的文件是sites-available目录内配置文件的符号链接。

/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;
/etc/nginx/sites-enabled/linuxize.com:    server_name linuxize.com   www.linuxize.com;

Grep仅显示文件名

要禁止默认grep输出并仅打印包含匹配模式的文件的名称,可以使用-l(或--files-with-matches)选项。

例如,搜索.conf以当前工作目录结尾的所有文件,并仅打印包含字符串linuxize.com类型的文件的名称:

grep -l linuxize.com *.conf

输出看起来像这样:

tmux.conf
haproxy.conf

-l选项通常与递归选项结合使用-R

grep -Rl linuxize.com /tmp

Grep案例不敏感

默认情况下,grep命令区分大小写,这意味着大写和小写字符被视为不同。

要在搜索时忽略大小写,请使用-i选项(或--ignore-case)。

例如,在Zebra没有任何选项的情况下搜索时,以下命令将不显示任何输出,即存在匹配的行。

grep Zebra /usr/share/words

但是如果使用该-i选项执行不区分大小写的搜索,它将匹配大写和小写字母:

grep -i Zebra /usr/share/words

指定“Zebra”将匹配“zebra”,“ZEbrA”或该字符串的大写和小写字母的任何其他组合。

zebra
zebra's
zebras

Grep Full Words

搜索gnugrep时,还会打印gnu嵌入较大单词的行,例如cygnusmagnum

grep gnu /usr/share/words
cygnus
gnu
interregnum
lgnu9d
lignum
magnum
magnuson
sphagnum
wingnut

要仅返回指定字符串为整个单词的行(由非单词字符括起),可以使用-w(或--word-regexp)选项。

单词字符包括字母数字字符(a-zA-Z0-9)和下划线(_)。所有其他字符都被视为非单词字符。

如果运行与上面相同的命令(包括该-w选项),则grep命令将仅返回gnu包含在单独单词中的那些行。

grep -w gnu /usr/share/words
gnu

Grep显示行号

要显示包含与模式匹配的字符串的行数,请使用-n(或--line-number)选项。使用此选项时,grep会将匹配打印到标准输出,前缀为其上的行号。

例如,要显示/etc/services包含bash前缀为匹配行号的字符串的文件中的行,可以使用以下命令:

grep -n 10000 /etc/services

下面的输出向我们显示匹配在行10423和10424上找到。

10423:ndmp            10000/tcp
10424:ndmp            10000/udp

Grep Count Matches

要将匹配行的计数打印到标准输出,请使用-c(或--count)选项。

在下面的示例中,我们计算了/usr/bin/zsh作为shell 的帐户数量。

grep -c '/usr/bin/zsh' /etc/passwd
4

Grep多个字符串(模式)

OR运算符可以连接两个或多个搜索模式|

默认情况下,Grep将模式解释为基本正则表达式,其中|必须使用元字符,例如失去其特殊含义和背面版本。

在下面的示例中,我们将搜索所有出现的单词fatalerrorcritical在Nginx日志错误文件中:

grep 'fatal\|error\|critical' /var/log/nginx/error.log

如果使用扩展正则表达式选项-E(或--extended-regexp),则不|应对运算符进行转义,如下所示:

grep -E 'fatal|error|critical' /var/log/nginx/error.log

Grep正则表达式

GNU Grep有两个正则表达式功能集,Basic和Extended。默认情况下,Grep将模式解释为基本正则表达式,要切换到扩展正则表达式,您需要使用该-E选项。

当在基本正则表达式模式中使用时,除元字符之外的所有其他字符实际上是与自身匹配的正则表达式。以下是最常用的元字符列表:

  • 使用^(插入符号)符号匹配行开头的表达式。在下面的示例中,^kangaroo仅当字符串出现在行的最开头时,该字符串才会匹配。

    grep "^kangaroo" file.txt
    
  • 使用$(美元)符号匹配行尾的表达式。在以下示例中,kangaroo$仅当字符串出现在行的最后时,该字符串才会匹配。

    grep "kangaroo$" file.txt
    
  • 使用.(句点)符号匹配任何单个字符。例如,要匹配以kan当时开头的任何内容有两个字符并以字符串结尾roo,您可以使用以下模式:

    grep "kan..roo" file.txt
    
  • 使用[ ](括号)匹配括号中的任何单个字符。例如,找到包含accept或“ 的行accent,您可以使用以下模式:

    grep "acce[np]t" file.txt
    
  • 使用[^ ](括号)匹配括号中的任何单个字符。以下模式将匹配包含的所有字符串组合co(any_leter_except_l )a,例如cocacobalt等等,但不匹配包含的行cola

    grep "co[^l]a" file.txt
    

要逃避下一个字符的特殊含义,请使用\(反斜杠)符号。

Grep扩展正则表达式

要将模式解释为扩展正则表达式,请使用-E(或--extended-regexp)选项。扩展正则表达式包括所有基本元字符,以及其他元字符,以创建更复杂和强大的搜索模式。以下是一些例子:

  • 匹配并提取给定文件中的所有电子邮件地址:

    grep -E -o "\b[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt
    
  • 匹配并提取给定文件中的所有有效IP地址:

    grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt
    

-o选项用于仅打印匹配的字符串。

比赛前的Grep打印线

要在匹配行之前打印特定数量的行,请使用-B(或--before-context)选项。

例如,要在匹配行之前显示5行前导上下文,可以使用以下命令:

grep -B 5 root /etc/passwd

匹配后Grep打印线

要在匹配行后打印特定数量的行,请使用-A(或--after-context)选项。

例如,要在匹配行后显示5行尾随上下文,可以使用以下命令:

grep -A 5 root /etc/passwd

结论

在本教程中,您学习了如何使用Grep搜索文件内部的模式。在Grep用户手册页面上可以了解更多有关Grep 的信息