如何在Linux上使用grep命令

Linux grep命令是一个字符串和模式匹配实用程序,可显示多个文件中的匹配行。它还可以使用来自其他命令的管道输出。我们教你怎么做。

GREP背后的故事

grep命令在Linux和Unix圈子里很有名,原因有三。首先,它非常有用。其次,丰富的选择可能是压倒性的。第三,它是在一夜之间写成的,以满足特定的需求。前两个很好,第三个稍微差一点。

肯·汤普森(Ken Thompson)从ed编辑器(发音为ee-dee)中提取了正则表达式搜索功能,并创建了一个小程序--供他自己使用--来搜索文本文件。在贝尔实验室,他的部门主管道格·麦克罗伊(Doug McIlroy)找到汤普森,描述了他的同事李·麦克马洪(Lee McMahon)面临的问题。

麦克马洪试图通过文本分析来确定联邦党论文的作者。他需要一种可以在文本文件中搜索短语和字符串的工具。那天晚上,汤普森花了大约一个小时的时间将他的工具变成一个可以被其他人使用的通用工具,并将其重命名为grep。他的名字取自ed命令字符串g/re/p,翻译过来就是“全局正则表达式搜索”。

你可以看汤普森和布莱恩·科尼根谈论GREP的诞生。

使用grep进行简单搜索

要在文件中搜索字符串,请在命令行上传递搜索项和文件名:

将显示匹配线。在本例中,它是单行。匹配的文本将突出显示。这是因为在大多数发行版中,grep别名为:

alias grep='grep --colour=auto'

让我们看一下有多行匹配的结果。我们将在应用程序日志文件中查找单词“Average”。因为我们记不起日志文件中的单词是否为小写,所以我们将使用-i(忽略大小写)选项:

grep -i Average geek-1.log

将显示每个匹配的行,并在每个行中突出显示匹配的文本。

我们可以使用-v(反转匹配)选项显示不匹配的行。

grep -v Mem geek-1.log

没有突出显示,因为这些是不匹配的行。

我们可以让grep完全沉默。结果作为grep的返回值传递给shell。结果为0表示找到该字符串,结果为1表示未找到该字符串。我们可以使用$?检查返回代码?特殊参数:

grep -q average geek-1.logecho $?grep -q howtogeek geek-1.logecho $?

使用grep进行递归搜索

要搜索嵌套目录和子目录,请使用-r(递归)选项。请注意,您没有在命令行上提供文件名,您必须提供路径。在这里,我们在当前目录中进行搜索“。以及任何子目录:

grep -r -i memfree .

输出包括每个匹配行的目录和文件名。

我们可以使用-R(递归取消引用)选项使grep跟随符号链接。我们在此目录中有一个符号链接,名为logs-Folder。它指向/home/dave/logs。

ls -l logs-folder

让我们使用-R(递归取消引用)选项重复上次搜索:

grep -R -i memfree .

跟随符号链接,grep也搜索它所指向的目录。

搜索整个单词

默认情况下,如果搜索目标出现在该行中的任何位置(包括在另一个字符串中),grep将与该行匹配。看看这个例子。我们要搜索“自由”这个词。

grep -i free geek-1.log

结果是包含字符串“free”的行,但它们不是单独的单词。它们是字符串“MemFree”的一部分。

要强制grep命令仅匹配单独的“word”,请使用-w(Word Regexp)选项。

grep -w -i free geek-1.logecho $?

这一次没有结果,因为搜索词“free”没有作为单独的单词出现在文件中。

使用多个搜索词

-E(扩展regexp)选项允许您搜索多个单词。(-E选项取代了不推荐使用的egrep版本的grep。)

该命令搜索两个搜索词“Average”和“memfree”。

grep -E -w -i "average|memfree" geek-1.log

显示每个搜索词的所有匹配行。

您还可以搜索多个词条,这些词条不一定是完整的单词,但也可以是完整的单词。

e(模式)选项允许您在命令行上使用多个搜索词。我们使用正则表达式括号功能来创建搜索模式。它告诉grep匹配方括号“[]”中包含的任何一个字符。这意味着grep在搜索时将匹配“kB”或“KB”。

两个字符串都匹配,实际上,有些行同时包含这两个字符串。

完全匹配的行

-x(行regexp)将只匹配整行与搜索词匹配的行。让我们搜索已知在日志文件中只出现一次的日期和时间戳:

grep -x "20-Jan--06 15:24:35" geek-1.log

找到并显示匹配的单行。

与之相反的是,只显示不匹配的行。这在您查看配置文件时会很有用。评论很棒,但有时很难在所有评论中找出实际设置。以下是/etc/sudoers文件:

我们可以有效地过滤出评论行,如下所示:

sudo grep -v "#" /etc/sudoers

这就更容易解析了。

仅显示匹配文本

有时您可能不想看到整个匹配的行,只想看到匹配的文本。o(唯一匹配)选项就是这样做的。

grep -o MemFree geek-1.log

显示减少到只显示匹配搜索词的文本,而不是显示整个匹配行。

使用grep进行计数

grep不仅仅是文本,它还可以提供数字信息。我们可以用不同的方式让grep为我们服务。如果我们想知道一个搜索词在一个文件中出现了多少次,可以使用-c(计数)选项。

grep -c average geek-1.log

grep报告该搜索词在此文件中出现了240次。

您可以使用-n(行号)选项让grep显示每个匹配行的行号。

grep -n Jan geek-1.log

每条匹配行的行号显示在该行的开头。

要减少显示的结果数,请使用-m(最大计数)选项。我们将把输出限制为五个匹配的行:

grep -m5 -n Jan geek-1.log

添加上下文

能够看到每个匹配行的一些附加行(可能是不匹配的行)通常很有用。它可以帮助区分哪些匹配的行是您感兴趣的。

要显示匹配行之后的一些行,请使用-A(上下文之后)选项。在本例中,我们要求三行代码:

grep -A 3 -x "20-Jan-06 15:24:35" geek-1.log

要查看匹配行之前的一些行,请使用-B(之前的上下文)选项。

grep -B 3 -x "20-Jan-06 15:24:35" geek-1.log

要包括匹配行之前和之后的行,请使用-C(上下文)选项。

grep -C 3 -x "20-Jan-06 15:24:35" geek-1.log

显示匹配的文件

要查看包含搜索词的文件名,请使用-l选项(匹配的文件)。要找出哪些C源代码文件包含对sl.h头文件的引用,请使用以下命令:

grep -l "sl.h" *.c

列出的是文件名,而不是匹配的行。

当然,我们可以查找不包含搜索词的文件。-L(不匹配的文件)选项就是这样做的。

grep -L "sl.h" *.c

线的起点和终点

我们可以强制grep只显示行首或行尾的匹配项。“^”正则表达式运算符与行的开头匹配。实际上,日志文件中的所有行都将包含空格,但我们将搜索第一个字符为空格的行:

grep "^ " geek-1.log

在行首显示以空格作为第一个字符的行。

要匹配行尾,请使用“$”正则表达式运算符。我们将搜索以“00”结尾的行。

grep "00$" geek-1.log

显示屏显示以“00”作为最后字符的行。

将管道与grep一起使用

当然,您可以将输入通过管道传输到grep,将grep的输出通过管道传输到另一个程序,并将grep置于管道链的中间。

假设我们希望看到字符串“ExtractParameters”在C源代码文件中的所有匹配项。我们知道将会有相当多的输出,所以我们通过管道将输出分成较少的部分:

grep "ExtractParameters" *.c | less

输出是以LESS格式显示的。

这使您可以浏览文件列表并使用Less的搜索功能。

如果我们通过管道将grep的输出传输到wc,并使用-l(行)选项,我们就可以计算源代码文件中包含“ExtractParameters”的行数。(我们可以使用grep-c(Count)选项来实现这一点,但这是演示从grep输出管道的一种很好的方式。)

grep "ExtractParameters" *.c | wc -l

使用下一个命令,我们将通过管道将ls的输出传输到grep,并将来自grep的输出传输到排序。我们将列出当前目录中的文件,选择其中包含字符串“aug”的文件,并根据文件大小对它们进行排序:

ls -l | grep "Aug" | sort +4n

让我们来分析一下这一点:

ls-l:使用ls执行文件的长格式列表。 grep“aug”:从ls清单中选择带有“aug”的行。请注意,这还会查找名称中包含“aug”的文件。 SORT+4N:在第四列(文件大小)上对grep的输出进行排序。

我们得到8月份修改过的所有文件的排序列表(与年份无关),按文件大小升序排列。

相关:如何在Linux上使用管道

格雷普:与其说是命令,不如说是盟友

grep是一个非常适合您使用的工具。它可以追溯到1974年,现在仍然很强大,因为我们需要它所做的事情,没有什么比它做得更好了。

将grep与一些正则表达式相结合-fu真的将它带到了一个新的层次。

相关:如何使用基本正则表达式更好地搜索并节省时间