Linux中的Grep命令(在文件中查找文本)

时间:2020-03-05 15:27:34  来源:igfitidea点击:

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

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

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

'grep'命令语法

'grep'命令的语法如下:

grep [OPTIONS] PATTERN [FILE...]

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

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

为了能够搜索文件,运行命令的用户必须对该文件具有读取权限。

在文件中搜索字符串

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

例如,要显示“/etc/passwd”文件中包含字符串“ bash”的所有行,可以运行以下命令:

grep bash /etc/passwd

输出应如下所示:

root:x:0:0:root:/root:/bin/bash
theitroad:x:1000:1000:theitroad:/home/theitroad:/bin/bash

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

grep "Gnome Display Manager" /etc/passwd

反转匹配(排除)

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

例如,要打印不包含字符串“ nologin”的行,可以使用:

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

使用Grep过滤命令的输出

可以使用'grep'通过管道过滤命令的输出,并且只有与给定模式匹配的行才会打印在终端上。

例如,要找出哪些系统以用户“ www-data”的身份在系统上运行,可以使用以下“ ps”命令:

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
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

递归搜索

要递归搜索模式,请使用'-r'选项(或者'--recursive')调用'grep'。
使用此选项时,“ grep”将搜索指定目录中的所有文件,并跳过递归遇到的符号链接。

要跟随所有符号链接,而不是'-r',请使用'-R'选项(或者'--dereference-recursive')。

这是一个示例,显示了如何在“/etc”目录内的所有文件中搜索字符串“ theitroad.com”:

grep -r theitroad.com /etc

输出将包含以文件的完整路径为前缀的匹配行:

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

如果使用'-R'选项,则'grep'将跟随所有符号链接:

grep -R theitroad.com /etc

注意下面输出的最后一行。
当用'-r'调用'grep'时,不会打印该行,因为Nginx的'sites-enabled'目录中的文件是指向'sites-available'目录中的配置文件的符号链接。

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

仅显示文件名

要取消默认的“ grep”输出并仅打印包含匹配模式的文件的名称,请使用“ -l”(或者“ --files-with-matches”)选项。

以下命令在当前工作目录中搜索所有以'.conf'结尾的文件,并仅显示包含字符串'theitroad.com'的文件的名称:

grep -l theitroad.com *.conf

输出将如下所示:

tmux.conf
haproxy.conf

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

grep -Rl theitroad.com /tmp

不区分大小写的搜索

默认情况下,“ grep”区分大小写。
这意味着将大写和小写字符视为不同的字符。

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

例如,当搜索不带任何选项的'Zebra'时,以下命令将不会显示任何输出,例如:有匹配的行:

grep Zebra /usr/share/words

但是,如果我们使用'-i'选项执行不区分大小写的搜索,则它将同时匹配大小写字母:

grep -i Zebra /usr/share/words

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

zebra
zebra's
zebras

搜索全词

搜索字符串时,“ grep”将显示该字符串嵌入较大字符串中的所有行。

例如,如果我们搜索“ gnu”,则将以较大的单词(例如“ cygnus”或者“ magnum”)嵌入“ gnu”的所有行都将匹配:

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

要仅返回指定字符串是整个单词(用非单词字符括起来)的那些行,请使用'-w'(或者'--word-regexp')选项。

单词字符包括字母数字字符('a-z','A-Z'和'0-9')和下划线('_')。
所有其他字符均视为非单词字符。

如果我们运行与上述相同的命令,包括'-w'选项,则'grep'命令将仅返回其中包含'gnu'作为单独单词的那些行。

grep -w gnu /usr/share/words
gnu

显示行号

'-n'(或者'--line-number')选项告诉'grep'显示包含与模式匹配的字符串的行的行号。
使用此选项时,“ grep”将匹配项打印到以行号为前缀的标准输出。

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

grep -n 10000 /etc/services

下面的输出显示在行10423和10424上找到了匹配项。

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

匹配统计

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

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

regular expressiongrep -c '/usr/bin/zsh' /etc/passwd
4

静音模式

'-q'(或者'--quiet')告诉'grep'在安静模式下运行,不要在标准输出上显示任何内容。
如果找到匹配项,则命令以状态'0'退出。
在要检查文件是否包含字符串并根据结果执行特定操作的shell脚本中使用“ grep”时,此功能很有用。

这是在“ if”语句中以安静模式使用“ grep”作为测试命令的示例:

if grep -q PATTERN filename
then
    echo pattern found
else
    echo pattern not found
fi

基本正则表达式

GNU Grep具有三个正则表达式功能集,即Basic,Extended和Perl兼容。

默认情况下,“ grep”将模式解释为基本的正则表达式,其中除元字符之外的所有字符实际上都是与自己匹配的正则表达式。

以下是最常用的元字符的列表:

  • 使用'^'(脱字符号)符号可在行首匹配表达式。在下面的示例中,字符串'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_letter_except_l)a'的字符串的任何组合,例如'coca','cobalt'等,但不会匹配包含'cola'的行,
grep "co[^l]a" file.txt

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

扩展正则表达式

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

  • 匹配并提取给定文件中的所有电子邮件地址:
grep -E -o "\b[A-Za-z0-9._%+-]+@[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'选项仅用于打印匹配的字符串。

搜索多个字符串(模式)

可以使用OR运算符'|'将两个或者多个搜索模式结合在一起。

默认情况下,“ grep”将模式解释为基本正则表达式,其中的元字符如“ |”失去其特殊含义,必须使用其反斜线版本。

在以下示例中,我们正在Nginx日志错误文件中搜索单词'fatal','error'和'critical'的所有出现:

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

如果我们使用扩展的正则表达式选项'-E',则运算符'|'不应逃脱,如下所示:

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

打印匹配之前的行

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

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

grep -B 5 root /etc/passwd

打印匹配之后的行

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

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

grep -A 5 root /etc/passwd