grep(regex)中的正则表达式和示例

时间:2020-01-09 14:16:35  来源:igfitidea点击:

在Linux和类似Unix的操作系统上,如何在正则表达式中使用grep命令?
如何在Linux中使用grep和正则表达式(regex)搜索文本/单词?

Linux随附GNU grep,它支持扩展的正则表达式。

GNU grep是所有Linux系统上的默认设置。

grep命令用于查找存储在服务器或工作站上任何地方的信息。
让我们看一下正则表达式的基础知识,以及如何在Linux和Unix之类的系统中使用正则表达式。

grep中的正则表达式

正则表达式不过是每个输入行要匹配的模式。
模式是字符序列。
以下是模式的示例:

^w1
w1|w2
[^ ]
foo
bar
[0-9]

三种正则表达式

grep可以理解三种不同类型的正则表达式语法,如下所示:

  • 基本(BRE)
  • 扩展(ERE)
  • perl(PCRE)

grep正则表达式示例

在/etc/passswd中搜索Hyman

grep 'Hyman' /etc/passwd

输出示例:

Hyman:x:1000:1000:,,,:/home/Hyman:/bin/bash
Hymangite:x:1001:1001::/home/Hymangite:/bin/sh
giteHyman:x:1002:1002::/home/giteHyman:/bin/sh

在任何情况下都可以搜索Hyman(即不区分大小写的搜索)

grep -i -w 'Hyman' /etc/passwd

在任何情况下都可以搜索Hyman或raj

grep -E -i -w 'Hyman|raj' /etc/passwd

最后一个示例中的PATTERN用作扩展的正则表达式。
在任何情况下,以下内容都将与单词Linux或UNIX相匹配:

egrep -i '^(linux|unix)' filename

如何匹配单个字符

.字符(句点或点)与任何一个字符匹配。
考虑以下demo.txt文件:

$ cat demo.txt

输出示例:

foo.txt
bar.txt
foo1.txt
bar1.doc
foobar.txt
foo.doc
bar.doc
dataset.txt
purchase.db
purchase1.db
purchase2.db
purchase3.db
purchase.idx
foo2.txt
bar.txt

让我们查找所有从购买开始的文件名:

grep 'purchase' demo.txt

接下来,我需要找到所有文件名,从购买开始,然后是另一个字符:

grep 'purchase.db' demo.txt

我们的最后一个示例查找所有以购买开始但以db结尾的文件名:

grep 'purchase..db' demo.txt

如何仅匹配点字符

点(.)在正则表达式中有特殊含义,即匹配任何字符。
但是,如果只需要匹配点(.)怎么办?
我想告诉我的grep命令,我需要实际的点(.)字符,而不是的正则表达式特殊含义。

您可以在点(.)前面加上(反斜杠),以使其转义:

grep 'purchase..' demo.txt
grep 'purchase.\.' demo.txt

锚点

您可以使用^和$来强制正则表达式分别仅在行的开头或结尾进行匹配。
以下示例显示仅以插孔开头的行:

grep ^Hyman /etc/passwd

输出示例:

Hyman:x:1000:1000:,,,:/home/Hyman:/bin/bash
Hymangite:x:1001:1001::/home/Hymangite:/bin/sh

您只能显示仅以单词Hyman开头的行,即不显示Hymangite,Hymang等:

grep -w ^Hyman /etc/passwd

查找以foo结尾的行:

grep 'foo$' filename

匹配仅包含foo的行:

grep '^foo$' filename

您可以使用以下示例搜索空白行:

grep '^$' filename

如何使用grep匹配字符集

点字符(.)匹配任何单个字符。
您可以使用[..]语法匹配特定字符和字符范围。
假设您要同时匹配插孔或插孔:

grep '[vV]ivek' filename

或者

grep '[vV][iI][Vv][Ee][kK]' filename

让我们匹配数字以及大小写字符。
例如,尝试对诸如Hyman1,Hyman2之类的单词进行数学运算:

grep -w '[vV]ivek[0-9]' filename

在此示例中,匹配两个数字。
换句话说,匹配foo11,foo12,foo22等,执行:

grep 'foo[0-9][0-9]' filename

您不限于数字,可以匹配至少一个字母:

grep '[A-Za-z]' filename

显示所有包含w或n字符的行:

grep [wn] filename

在方括号表达式中,用[:和:]括起来的字符类的名称代表该类所有字符的列表。
标准字符类名称为:

  • [[:alnum:]]字母数字字符。
  • [[:alpha:]]字母字符
  • [[:blank:]]空白字符:空格和制表符。
  • [[:digit:]]数字:0 1 2 3 4 5 6 7 8 9。
  • [[:lower:]]小写字母:a b c d e f g h i j k l m n o p q r s t u v w x y z。
  • [[:space:]]空格字符:制表符,换行符,垂直制表符,换页,回车和空格。
  • [[:upper:]]大写字母:A B C D E F G H I J K L M N O P Q R S T U V W X YZ。

在此示例中,匹配所有大写字母:

grep '[:upper:]' filename

如何否定集合中的匹配

^否定集合中的所有范围:

grep '[vV]ivek[^0-9]' test

使用grep正则表达式搜索文本模式

通配符

您可以使用。
进行单个字符匹配。
在此示例中,匹配所有以b开头并以t结尾的3个字符的单词:

grep '\<b.t\>' filename

其中:

  • \ <匹配单词开头的空字符串
  • >匹配单词末尾的空字符串。

用正好两个字符打印所有行:

grep '^..$' filename

显示以点和数字开头的任何行:

grep '^\.[0-9]' filename

转义点

假设您只想匹配IP地址192.168.2.254,仅此而已。
以下用于查找IP地址192.168.1.254的正则表达式将不起作用(还记得点匹配任何单个字符吗?
):

grep '192.168.1.254' hosts

输出示例:

192.168.2.18        centos7
192x168y2z18        centos7

所有三个点都需要转义:

192.168.2.18        centos7
grep '192\.168\.1\.254' hosts

以下示例仅匹配一个IP地址:

egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' file

如何搜索具有前导符号的模式?

使用-e选项搜索所有与test匹配的行如果不使用-e,grep会尝试将test解析为选项列表:

grep -e '--test--' filename

我该怎么办或使用grep?

使用以下语法:

grep -E 'word1|word2' filename
### OR ###
egrep 'word1|word2' filename

或者

grep 'word1\|word2' filename

如何与grep结合使用?

使用以下语法显示同时包含word1和word2的所有行

grep 'word1' filename | grep 'word2'

或者

grep 'foo.*bar\|word3.*word4' filename

如何测试序列?

您可以使用以下语法测试字符必须按顺序重复的频率:

{N}
{N,}
{min,max}

匹配字符v两次:

egrep "v{2}" filename

以下将同时匹配col和酷词:

egrep 'co{1,2}l' filename

我们的下一个示例将匹配至少三个字母c的任何行。

egrep 'c{3,}' filename

在此示例中,我将匹配以下格式的手机号码91-1234567890(即TwoDigit-TenDigit)

grep "[[:digit:]]\{2\}[ -]\?[[:digit:]]\{10\}" filename

如何使用grep突出显示?

传递--color如下:

grep --color regex filename

如何仅显示匹配项而不是整行?

使用以下语法:

grep -o regex filename

grep正则表达式运算符

我希望下表可以帮助您在Linux或类似Unix的系统上使用时快速理解grep中的正则表达式:

运算符意义例子
.匹配任何单个字符。grep '.' file

grep 'foo.' input
? | 上一项是可选的,最多匹配一次。 | grep 'igift?' /etc/passwd
* | 前一项将被匹配零次或多次。 | grep 'igift*' /etc/passwd
+ | 前一项将被匹配一次或多次。 | ls /var/log/ | grep -E "^[a-z]+.log."
{N} | 上一项完全匹配N次。 | egrep '[0-9]{2} input
{N,} | 前一项匹配N次或更多次。 | egrep '[0-9]{2,} input
{N,M} | 前一项至少匹配N次,但不超过M次。 | egrep '[0-9]{2,4} input
- | 表示范围,如果它不是列表中的第一个或最后一个,也不是列表中某个范围的终点。 | grep ':/bin/[a-z]*' /etc/passwd
^ | 匹配行首的空字符串;也代表不在列表范围内的字符。 | grep '^igift' /etc/passwd
grep '[^0-9]*' /etc/passwd
$ | 匹配行尾的空字符串。 | grep '^$' /etc/passwd
\b | 匹配单词边缘的空字符串。 | grep '\bigift' /etc/passwd
\B | 匹配空字符串,前提是它不在单词的边缘。 | grep '\B/bin/bash /etc/passwd
\< | 匹配单词开头的空字符串。 | grep '\'
\> | 匹配单词末尾的空字符串。 | grep 'bash\>' /etc/passwd

Linux grep vs egrep命令

egrep与grep -E命令相同。
它将PATTERN解释为扩展的正则表达式。

In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{,
       \|, \(, and \).

       Traditional egrep did not support the { meta-character, and some egrep implementations support \{ instead, so portable scripts should avoid  {  in
       grep -E patterns and should use [{] to match a literal {.

       GNU grep -E attempts to support traditional usage by assuming that { is not special if it would be the start of an invalid interval specification.
       For example, the command grep -E '{1' searches for the two-character string {1 instead of reporting a syntax  error  in  the  regular  expression.
       POSIX.2 allows this behavior as an extension, but portable scripts should avoid it.