grep 用法详解

三大文本处理工具之 grep。

语法格式

grep [选项] "匹配模式" [文件]

常用功能选项

  • -v:反向选择
  • -n:显示行号
  • -w:完整匹配一个单词,而不能只是匹配单词中的片段
  • -c:统计有多少文本行被匹配到了。
  • -o:只显示被模式匹配到的字符串。
  • --color:将匹配内容高亮显示。
  • -i:忽略大小写。
  • -E:开启扩展(Extend)的正则表达式。

多行显示:

多行显示,适用于显示配置内容,例如 nginx.conf 配置,需要查看所有的目录配置,那么可以使用多行显示选项查看配置的上下文。

  • -A n:显示匹配的字符串及后面 n 行。
  • -B n:显示匹配的字符串及前面 n 行。
  • -C n:显示匹配的字符串及前后 n 行。

查找文件的两种形式

直接指明文件。

grep "root" /etc/passwd

通过管道输入

cat /etc/passwd | grep "root"

同时匹配多个条件

使用管道,多个条件过滤

grep -v root /etc/passwd | grep -v nologin

查找整个目录

文本处理工具能够处理一个文件,如果要在大量的文件之中进行查找执行内容,一个个文件的匹配就太慢了,可以使用 grep 直接查找整个目录。

# 匹配当前目录下的所有文件,是否包含 test 字符串,将返回匹配的文本行
grep -r "test" *
# 匹配所有文件,返回包含目标行的文件名称
grep -l -r "test" *

理解基本例子

例1:查找当前目标下,含有 prog 前缀的文件内容中,包含 test 字符串的部分

grep test prog*

例2:递归遍历目标下,包含指定文件的内容。

grep -r update /etc/acpi

例3:反向查找,文件内容

grep -v test *test*

匹配模式

基本匹配的例子:

统计 test.file 文件中 test 字符串的个数。

grep -c "test" test.file

匹配模式,是基于正则表达式的,可以匹配字符,如下:

  • . 任意字符
  • [abc] 匹配 abc 字符中的一个
  • [a-zA-Z] 匹配字母表 52 个字母中的一个
  • [^123] 匹配以字符 123 中的一个开头的字符串

预定义字符集:

  • A-Za-z 等价于 [:alpha:]
  • 0-9 等价于 [:digit:]
  • A-Za-z0-9 等价于 [:alnum:]
  • tab, space 等价于 [:space:]
  • A-Z 等价于 [:upper]
  • a-z 等价于 [:lower]
  • 标点符号集合 等价于 [:punct:]

例子:

grep "hello" [^[A-Z]][[a-z]] test.file
# 等价于
grep "hello [^[:upper:]][[:digit:]]" test.file

控制匹配次数

上述匹配模式,都是对字符匹配一次。我们可以给其添加匹配次数规则。

  • \{m,n\}:匹配前面出现的字符 m 到 n 次。
  • \?:匹配前面出现的字符 0 次或者 1次。
  • *:匹配前面的内容出现任意次,可以是 0 次。

例子:

# 匹配任意 xxsh 字符串
grep "/.\{0,2\}sh" /etc/passwd
# 匹配 xxsh 四字单词
grep -w ".\{0,2\}sh" /etc/passwd

位置锚定

位置锚定,包括以下类型:

  • ^:锚定行首
  • $:锚定行尾
  • ^$:匹配空白行
  • \b或\<:锚定单词的词首
  • \b或\>:锚定单词的词尾
  • \B :与\b作用相反。

分组引用

grep 中分组的基本原理,和正则匹配式一样,使用括号进行包裹。

能够将字符串作为一个整体,方便后面进行使用。包括以下基本用法:

  • \1:引用第一个括号匹配的内容。
  • \2:引用第二个括号匹配的内容。
  • \n:引用第 n 个括号匹配的内容。

例子:

匹配一个首尾的字符/字母相同的行。

grep "^\([[:alpha:]]\).*\1$" test.file

可以看到上述第一个括号中,代表了第一个字母的内容。后面定义了以相同的字母进行结尾。

拓展匹配的正则模式

在上面的例子中,我们可以看到,由于在字符串中需要对特殊字符进行转移,所以需要使用大量反斜杠。例如 \(,不方便并且难以阅读。

使用 -e 选项或者 egrep 工具可以默认转义,不再使用反斜杠对特殊符号进行修饰。

如下:

  • \{m,n\} 等价于 {m,n}
  • \? 等价于 ?

例子

匹配四字字符串,以下三种方式等价。

grep ".\{0,2\}sh" /etc/passwd
grep -e ".{0,2}sh" /etc/passwd
egrep ".{0,2}sh" /etc/passwd

正则的多种条件

多种条件常用于特定规则语句的匹配,比如电话号码等等。我们使用 | 符号对每个字符单元进行指定规则。

例子:

匹配小于 100 以下的所有数字。

egrep "[0-9]|[1-9][0-9]" test.file