grep 是 Linux 中用于文本处理的最有用和功能最强大的命令之一。在本文中,我们将探讨如何在 grep 的 GNU 版本中使用正则表达式的基础,该版本在大多数 Linux 操作系统中默认可用
grep是 Linux 中用于文本处理的最有用和功能最强大的命令之一。grep在一个或多个输入文件中搜索与正则表达式匹配的行,并将每条匹配的行写入到标准输出。
正则表达式是与一组字符串匹配的模式。模式由运算符,文字字符和元字符组成,它们具有特殊的含义。GNUgrep支持三种正则表达式语法 Basic,Extended 和 Perl-compatible。
当没有给出正则表达式类型时,grep以 Basic 的形式调用,grep将搜索模式解释为基本 Basic 正则表达式。要将模式解释为扩展 Extended 的正则表达式,请使用-E/--extended-regexp选项。
在 GNUgrep的实现中,基本正则表达式和扩展正则表达式语法之间在功能上没有区别,且两者一样。
唯一的区别是,在基本正则表达式中的元字符?,+,{,|,(和)被解释为文字字符,即不将这些字符作为正则解释。
为了在使用基本正则表达式时保持元字符的特殊含义,必须使用反斜杠\对字符进行转义。稍后我们将解释这些和其他元字符的含义。
通常,您应始终将正则表达式括在单引号中,以避免 shell 解释和执行元字符在 shell 在意义。
grep命令的最基本用法是在文件中搜索字符或字符串。除了在可以搜索文件的内容之外,grep 还可以搜索标准输入的内容。
例如要搜索使用bash作为默认的登录 shell 用户,则可以在/etc/passwd文件中搜索包含bash字符串的所有行。
以下grep命令将搜索文件的内容,然后打印包含使用 bash 作为登录 shell 的用户:
grep bash /etc/passwd
输出应如下所示:
root:x:0:0:root:/root:/bin/bash
myfreax:x:1000:1000:myfreax:/home/myfreax:/bin/bash
在此示例中,字符串bash是一个基本的正则表达式,由四个字符组成。这告诉grep搜索紧随其后的b,a,s,h字符串。
默认情况下,grep命令区分大小写。这意味着将大写和小写字符视为不同的字符。要在搜索时忽略大小写,请使用-i/--ignore-case选项。
值得一提的是grep将搜索模式作为字符串而不是单词进行搜索 / 查找。因此,如果您要搜索gnu,grep还将打印在较大的单词中嵌入 gnu 的行。例如cygnus或magnum。
如果搜索一个完全限定的字符串或者包含空格的字符串,则需要将其用单引号或双引号引起来,这:
grep "Gnome Display Manager" /etc/passwd
^脱字符号表示与行的开头的字符串匹配。如果正则表达式以^开头,grep将在每行的开头开始匹配^之后的字符串。
以下grep命令将从文件file.txt中搜索以字符串linux开头的行:
grep '^linux' file.txt
$美元符号与行的结尾字符串匹配。$之后表示你需要搜索的内容。grep将在每行的行尾匹配$之后的字符串。
以下grep命令将从文件file.txt中搜索以字符串 linux 结尾的行:
grep 'linux$' file.txt
除了搜索行的开头和结尾,您还可以组合使用由^关键词$构造的正则表达式。将允许搜索指定的内容,不是嵌入大字符串匹配的行。
另一个有用的例子是组合使用^$模式匹配所有空行,即开头与结束都没有内容。这在查找空行时特别有用。
以下grep命令将从文件file.txt中搜索仅包含linux的行:
grep '^linux$' file.txt
.符号是与任何单个字符匹配的元字符。
例如,要包括 kan,然后有两个字符并以字符串 roo” 结尾的任何内容,则可以使用以下模式:
grep 'kan..roo' file.txt
[]中括号表达式允许将字符括在中括号[]来匹配一组字符。即从中括号[]内的字符串任意使用一个字符来匹配行。
例如,以下grep命令将从文件file.txt中搜索包含accept或accent的行:
grep 'acce[np]t' file.txt
如果方括号内的第一个字符是符号^,则它将匹配方括号中未括起来的任意字符。
以下模式将匹配包含除l之外的co.a字符串,.表示任意字符。例如coca,cobalt的任意字符串组合,但不匹配包含cola的行 。
例如,以下grep命令将从文件file.txt中搜索不cola的行:
grep 'co[^l]a' file.txt
您可以通过指定以连字符分隔的范围的第一个和最后一个字符来构造范围表达式,在中括号表达式内指定一系列字符,而不是一个一个地写完所有字符。
例如,[a-e]等同于[abcde],[1-3]等同于[123]。以下表达式匹配以大写字母开头的每一行:
grep '^[A-Z]' file.txt
grep还支持中括号包含的预定义字符类别。[:alnum:]表示匹配单个数字与字母字符,与[0-9A-Za-z]一样。[:alpha:]表示匹配单个字母字符,与[A-Za-z]一样。
[:blank:]表示匹配单个空格和制表符。[:digit:]表示匹配单个数字0 1 2 3 4 5 6 7 8 9。
[:lower:] 表示匹配单个小写字母字符,与[a-z]一样。[:upper:] 表示匹配单个大写字母,与[A-Z]一样。
量词可让您指定匹配项必须出现的次数,即匹配关键词可以被多次匹配。以下是一些 GNUgrep支持的量词。
*表示匹配零次或者多次。?表示将前一项匹配零或一次,+表示匹配前一项一次或多次。{n} 匹配前一项n次,n是数字。
{n,}至少匹配 n 次。{,m}最多匹配前一项 m 次。 {n,m} 匹配前一项必须出现次数是从 n-m 次,如果是 {2,4},即 2 至 4 次。
现在我们已经了解正则表达式的量词,接下来我们将使用量词作为示例。在 grep 使用量词进行搜索,以及如何避免 shell 解释特殊字符*,?等。
*字符与前面的字符匹配零次或多次。以下grep命令示例将匹配sright,right,ssright等。
正则表达式s*right的*量词表示匹配 s 字符零次或者多次,即没有上限,可以是很多sssss。's*right'给正则表达式使用单引号,也是避免 shell 解释特殊字符的方式。
echo right | grep 's*right'
echo ssright | grep 's*right'
以下是更高级的模式,它匹配所有以大写字母开头,以句点或逗号结尾的行。.*正则表达式表示匹配任意数量的任何字符。
以下grep命令-E选项表示使用扩展正则表达式。^表示行的开始位置,[A-Z]表示 A 到大 Z:
grep -E '^[A-Z].*[.,]$' file.txt
?使前一字符成为可选,并且只能匹配一次。以下 grep 命令将同时匹配bright和right。
你会这里的?字符的前面多了反斜杠。如果你使用的是基本正则表达式则需要反斜杠转义?字符避免 shell 的解释与执行。
grep 'b\?right' file.txt
以下grep -E是使用扩展正则表达式的方式匹配'\b?right'模式,因此不需要转义那些有特殊含义的字符。
grep -E 'b?right' file.txt
+字符与上一项匹配一次或多次。 以下将匹配sright和ssright,但不匹配right。
以下 grep 命令选项-E表示使用扩展正则表达式,模式's+'表示必须存在一个s或者多个s字符,没有上限。
grep -E 's+right' file.txt
大括号字符{}允许您指定确切的数字,匹配次数必须在指定的范围内。以下 grep 命令将匹配 3 到 9 位数字的整数。
在以下'[[:digit:]]{3,9}'模式中,[:digit:] 表示 0 到 9 的数字,[[:digit:]]则表示 [0-9],{3,9}表示匹配 3 到 9 次,即可行必须包含有 3 到 9 个连续的数字。
grep -E '[[:digit:]]{3,9}' file.txt
竖线|或运算符使您可以指定不同的可能匹配项,这些匹配项可以是文字字符串或正则表达式。在所有正则表达式运算符中,此运算符的优先级最低。
在下面的示例中,我们搜索Nginx 的错误日志文件中出现单词fatal,error和critical行,如果使用扩展的正则表达式,则不需要对|进行转义。
grep 'fatal\|error\|critical' /var/log/nginx/error.log
grep -E 'fatal|error|critical' /var/log/nginx/error.log
分组是正则表达式的一项功能,可让您将模式分组并将其作为引用。可使用括号()创建分组。使用基本正则表达式时,必须用反斜杠\对括号进行转义。
正则表达式可以有多个组。结果,匹配捕获的组通常保存在数组中,数组的成员与匹配的组顺序相同。这通常只是匹配组本身的顺序。
匹配的组保存在数组中,如果需要对捕获的组进行引用。可使用$1, ..., $9对捕获的组进行引用。
以下示例同时匹配fear和less。 量词?使(fear)组成为可选。
grep -E '(fear)?less' file.txt
GNUgrep包含几个由反斜杠和常规字符组成的元字符。以下是一些最常见的特殊反斜杠表达式。
\b匹配单词边界。<匹配单词开头的空字符串。>在单词末尾匹配一个空字符串。\w匹配一个单词。\s匹配空格。
以下模式将匹配单独的单词abject和object。 如果嵌入较大的单词,则不会匹配这些单词:
grep '\b[ao]bject\b' file.txt