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

grep在一个或多个输入文件中搜索与指定模式匹配的行,并将匹配行写入标准输出。如果未指定文件,grep则从标准输入读取内容。

grep命令读取的标准输入通常是另一个命令的输出。在本教程中,我们将通过实际示例向您展示如何使用grep命令并详细说明最常用的GNU grep选项。

grep 命令

在开始使用grep命令之前,让我们先回顾一下grep基本语法。grep命令的语法形式是grep [OPTIONS] PATTERN [FILE...]

OPTIONS可选参数可以零个或多个选项,PATTERN搜索模式可以是字符串,也可以是正则表达式。

FILE零个或多个输入文件名。要能够搜索文件,运行grep命令的用户必须对文件具有读取权限。

grep 搜索字符串

grep命令的最基本用法是在文件中搜索字符串。如果字符串包含空格,则需要将其用单引号或双引号引起来。

例如命令grep "Gnome Display Manager" /etc/passwd在文件/etc/passwd搜索Gnome Display Manager

命令grep bash /etc/passwd在文件/etc/passwd包含字符串bash的行。

grep bash /etc/passwd
grep "Gnome Display Manager" /etc/passwd
root:x:0:0:root:/root:/bin/bash
myfreax:x:1000:1000:myfreax:/home/myfreax:/bin/bash

grep 排除与反转匹配

要仅打印与搜索模式不匹配的行,可以使用grep命令的-v--invert-match选项进行反转的匹配。

注意grep会区分大小写。这意味着大写和小写被视为不同的字符。要在搜索时忽略大小写,使用-i选项调用grep

如果搜索字符串包含空格,只需要将其括在单引号或双引号中。grep就会搜索空格,你也可以使用正则表达式表示空格的匹配。

例如命令ps aux | grep fnord | grep -v grep 在搜索进程的时候排除自身的进程。

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
myfreax:x:1000:1000:myfreax:/home/myfreax:/bin/bash

grep 搜索标准输入

除了指定搜索文件之外,您还可以将另一个命令的标准输出传递给grep命令通过管道,然后仅打印与指定模式匹配的行。

例如命令ps -ef | grep www-data 使用ps命令列出所有进程然后通过管道传递grep命令搜索www-data用户运行的进程。

如果在搜索结果不多的时候,你很容易就会发现ps -ef | grep www-data命令的标准输出还包含当前grep进程的信息。

如果您不希望打印grep进程的信息,可将标准输出再次通过管道传递到另一个grep实例排除grep进程的输出。例如命令ps -ef | grep www-data | grep -v grep

ps -ef | grep www-data
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 递归搜索目录文件

要进行递归搜索目录请使用grep命令的-r或者-R选项。gerp命令将以文件路径为前缀打印匹配的行,并使用冒号:分隔。

grep命令的-r-R选项的不同之处在于,-r选项仅递归目录和普通文件,但不包括符号链接,也就是软链接。-R选项则包括软链接。

例如命令grep -r myfreax.com /etc将在/etc目录内搜索包含myfreax.com字符串的所有文件。

grep -r myfreax.com /etc
grep -R myfreax.com /etc

grep 仅打印文件名

默认gerp命令将以文件路径为前缀打印匹配的行,并使用冒号:分隔。要仅打印包含匹配模式的文件名,可以使用grep命令-l/--files-with-matches选项。

例如命令grep -l myfreax.com *.conf将在当前工作目录搜索以.conf结尾的文件。

并仅打印包含字符串myfreax.com的文件名称。你也可以组合-l选项与-R选项进行递归搜索文件。

grep -l myfreax.com *.conf
grep -Rl myfreax.com /tmp
tmux.conf
haproxy.conf

grep 不区分大小写

默认情况下grep命令区分大小写。这意味着将大写和小写字符视为不同的字符。要在搜索时忽略大小写,请使用grep命令的-i/--ignore-case选项。

​​例如命令grep Zebra /usr/share/words将搜索Zebra。但是,如果使用-i选项执行不区分大小写的搜索,则它将同时匹配大小写字母。

grep Zebra /usr/share/words
grep -i Zebra /usr/share/words
zebra
zebra's
zebras

grep 搜索单词

在搜索gnu时,grep命令还将打印gnu嵌入在较大字词的行,例如cygnusmagnum

单词字符包括a-zA-Z0-9和下划线_。所有其他字符都被视为非单词字符,例如$等。

要仅搜索指定字符串是整个单词的行,请使用grep命令的-w/--word-regexp选项。

grep gnu /usr/share/words
grep -w gnu /usr/share/words
gnu

grep 打印行号

要打印与模式匹配的行号,请使用grep命令的-n/--line-number选项。grep命令将以行号作为前缀打印匹配的行。

例如命令grep -n 10000 /etc/services/etc/services文件搜索包含1000数值的行。

grep -n 10000 /etc/services
393:webmin		10000/tcp

grep 统计匹配行数

要仅打印与搜索模式匹配的行数,请使用grep命令的-c/--count选项。

例如命令grep -c '/usr/bin/zsh' /etc/passwd统计以/usr/bin/zsh为默认shell的用户数量。

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

grep 指定多个搜索模式

grep命令允许你使用或运算符|组合多个搜索模式搜索文件。默认情况下,grep将模式解释为基本正则表达式。

当你在基本正则表达式中使用使用OR运算符|时,必须使用反斜杠\进行转义。因为shell会将|解释为Shell管道。

如果在grep命令指定选项-E/--extended-regexp使用的是扩展正则表达式,则不应对或运算符|进行转义。

在下面的示例中,我们在Nginx错误日志文件中搜索单词fatalerrorcritical匹配的行。

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

grep 不打印标准输出

grep命令的-q/--quiet选项指示不向终端写入任何内容,通常是标准输出。如果搜索到匹配的行,grep命令的退出代码是0。

这样就可以在Shell脚本使用if语句和grep静默模式,判断文件是否包含指定的字符串。

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

grep 正则表达式基础

GNUgrep支持三种正则表达式语法,Basic、Extended和Perl-compatible。默认情况下,grep将模式解释为Basic正则表达式。

当你在正则表达式中使用使用OR运算符|时,必须使用反斜杠\进行转义。因为shell会将|解释Linux管道。

如果你使用的扩展正则表达式,则|不不需要转义,即不需要反斜杠\-E选项指示grep命令使用扩展正则表达式。

^符号匹配行首,$符号匹配行尾,. 符号以匹配任意单个字符,[ ]中括号匹配指定范围的字符,[^ ]以匹配非中括号内的任意字符。

例如命令grep -Ewv 'nologin|bash' /etc/passwdgrep -wv 'nologin\|bash' /etc/passwd是等效的,前者使用的是扩展表达式,后者使用基本正则表达式。

grep -Ewv 'nologin|bash' /etc/passwd

grep -wv 'nologin\|bash' /etc/passwd

grep 打印匹配行前半与后半部分

要在匹配行之前打印指定数量的行,请使用-B/--before-context选项。要在匹配的行之后打印指定数量的行,请使用-A/--after-context选项。

例如,要在匹配的行之前打印前五行,请运行命令grep -B 5 root /etc/passwd

命令grep -A 5 root /etc/passwd在匹配的行之后显示尾随五行。这个有点类似在指定位置截断。

grep -B 5 root /etc/passwd
grep -A 5 root /etc/passwd

grep 电子邮件地址

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

grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt

grep IP地址

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

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

结论

grep命令允许您使用指定的模式或者正则表达式搜索文件。如果找到匹配的行,grep将打印包含指定模式的行。

请访问Grep用户手册页面,要了解Grep的更多信息。如果您有任何问题或反馈,请随时发表评论。