Grep 命令中的正则表达式

grep 是 Linux 中用于文件处理的最有用和功能最强大的命令之一。 grep 在一个或多个输入文件中搜索与正则表达式匹配的行,并将每个匹配的行写入标准输出。

在本文中,我们将探讨在 GNU 版本的 grep 中如何使用正则表达式的基础知识, 大多数 Linux 操作系统默认情况下都提供了正则表达式。

Grep 正则表达式

正则表达式或正则表达式是与一组字符串匹配的模式。模式由运算符,构造文字字符和元字符组成,它们具有特殊的含义。 GNU grep 支持三种正则表达式语法, Basic , Extended 和 Perl 兼容。

以最简单的形式,当没有给出正则表达式类型时, grep 将搜索模式解释为基本正则表达式。要将模式解释为扩展的正则表达式,请使用 -E( 或 --extended-regexp) 选项。

在 GNU grep 的实现中,基本正则表达式和扩展正则表达式语法之间在功能上没有区别。唯一的区别是,在基本的正则表达式的元字符 ?+{|( ,和 ) 被解释为文字字符。为了在使用基本正则表达式时保持元字符的特殊含义,必须使用反斜杠 (\) 对字符进行转义。稍后我们将解释这些和其他元字符的含义。

通常,您应始终将正则表达式括在单引号中,以避免 shell 解释和扩展元字符。

文字匹配

grep 命令最基本的用法是在文件中搜索文字字符或一系列字符。例如,要显示 /etc/passwd 文件中包含字符串 “ bash” 的所有行,您将运行以下命令:

grep bash /etc/passwd

输出应如下所示:

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

在此示例中,字符串 “bash” 是由四个文字字符组成的基本正则表达式。这告诉 grep 您搜索具有紧随其后的 “b” , “a” , “s” 和 “h” 的字符串。

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

重要的是要注意, grep 将搜索模式视为单词而不是字符串。因此,如果您要搜索 “gnu” , grep 还将打印以较大的嵌入 “gnu” 的单词(例如 “cygnus” 或 “magnum”)的行。

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

grep "Gnome Display Manager" /etc/passwd

定位符

定位符是元字符,可让您指定必须在该行中找到匹配项的位置。

^(尖)符号匹配一行的开头。在以下示例中,仅当字符串 “linux” 出现在行的开头时才匹配。

grep '^linux' file.txt

$ (美元)符号匹配一行的结尾。要找到以字符串 “linux” 结尾的行,可以使用:

grep 'linux$' file.txt

您还可以使用两个定位符构造一个正则表达式。例如,要查找仅包含 “linux” 的行,请运行:

grep '^linux$' file.txt

另一个有用的示例是 ^$ 匹配所有空行的模式。

匹配单个字符

元字符 . 点符号匹配任何单个字符。例如,要匹配以 “kan” 开头,然后有两个字符并以字符串 “ roo” 结尾的任何内容,则可以使用以下模式:

grep 'kan..roo' file.txt

方括号表达式

方括号表达式允许将一组字符括在方括号中来匹配它们 [] 。例如,找到包含 “accept” 或 “accent” 的行,可以使用以下表达式:

grep 'acce[np]t' file.txt

如果方括号内的第一个字符是插入符号 ^,则它匹配方括号中未包含的任何单个字符。以下模式将匹配以 “co” 开头的字符串的任何组合,后接除 “l” 之外的任何字母(例如 “coca” , “cobalt” 等),但不匹配包含 “cola” 的行”:

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

您可以在方括号内指定一系列字符,而不是一个一个地放置字符。通过指定以连字符分隔的范围的第一个和最后一个字符来构造范围表达式。例如, [a-e] 等效于 [abcde][1-3] 并且等效于 [123]

以下表达式匹配以大写字母开头的每一行:

grep '^[A-Z]' file.txt

grep 还支持括号内预定义的字符类。下表显示了一些最常见的字符类:

量词 角色类
[:alnum:] 字母数字字符。
[:alpha:] 字母字符。
[:blank:] 空格和制表符。
[:digit:] 数字。
[:lower:] 小写字母。
[:upper:] 大写字母。

有关所有字符类的完整列表,请参阅 Grep 手册

量词

量词允许您指定要出现的匹配项必须出现的次数。下表显示了 GNU grep 支持的量词:

量词 描述
* 匹配上一项零次或多次。
? 匹配上一项零或一次。
+ 将上一项匹配一次或多次。
{n} 匹配上一项 n 次。
{n,} 匹配前一项至少 n 次。
{,m} 匹配上一项最多 m 次。
{n,m} 匹配前一项匹配 nm 次。

*(星号)的字符前述项零次或多次匹配。以下将匹配 “right”,“sright”,“ssright” 等等。

grep 's*right'

下面是更高级的模式,它匹配所有以大写字母开头,以句点或逗号结尾的行。正则表达式 .* 匹配任何数量的任何字符:

grep -E '^[A-Z].*[.,]$' file.txt

?(问号)字符使前面的项目可选择的,它只能匹配一次。以下将同时匹配 “bright” 和 “right”。该 ? 字符与反斜线,因为我们使用的是基本的正则表达式:

grep 'b\?right' file.txt

这是使用扩展正则表达式的正则表达式:

grep -E 'b?right' file.txt

+ (加)字符匹配前述项的一个或多个次。以下将匹配 “sright” 和 “ssright”,但不匹配 “right”:

grep -E 's+right' file.txt

大括号字符{}允许您指定确切的数字,上限或下限或发生匹配必须发生的范围。

以下内容匹配 3 到 9 位之间的所有整数:

grep -E '[[:digit:]]{3,9}' file.txt

或者

术语交替是简单的 “或”。交替运算符 | (管道)允许您指定不同的可能匹配项,这些匹配项可以是文字字符串或表达式集。在所有正则表达式运算符中,此运算符的优先级最低。

在下面的例子中,我们在 Nginx 的错误日志文件中寻找的所有 fatalerror 以及 critical 关键词错先的行:

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

如果使用扩展的正则表达式,则不应对 | 运算符进行转义,如下所示:

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

分组

分组是正则表达式的一项功能,可让您将模式分组在一起并将其作为一项引用。使用括号 () 创建组。

使用基本正则表达式时,必须使用反斜杠 (\) 对括号进行转义。

下面的示例同时匹配 “fearless” 和 “less” 。该 ? 量词使 (fear) 组可选:

grep -E '(fear)?less' file.txt

反斜杠特殊表达式

GNU grep 包含几个元字符,由反斜杠和常规字符组成。下表显示了一些最常见的特殊反斜杠表达式:

表达 描述
\b 匹配单词边界。
\< 在单词开头匹配一个空字符串。
\> 在单词末尾匹配一个空字符串。
\w 匹配一个单词。
\s 匹配一个空格。

以下模式将匹配单独的单词 “abject” 和 “object” 。如果嵌入较大的单词,它将不匹配单词:

grep '\b[ao]bject\b' file.txt

结论

正则表达式广泛使用在文本编辑器,编程语言,以及诸如命令行工具中,比如: grepsedawk 。在搜索文本文件,编写脚本或过滤命令输出时,了解如何构造正则表达式将非常有帮助。