正则表达式简介

来自菜鸟教程
跳转至:导航、​搜索

介绍

作为系统管理员、开发人员、QA 工程师、支持工程师等。 需要从文件中找到特定模式,例如属于某个范围的一组 IP 地址或一系列时间戳或一组域或子域名。 可能还需要查找以特定方式拼写的单词或查找文件中可能的拼写错误。 这就是正则表达式的用武之地。

正则表达式是匹配模式(或有时不匹配模式)的模板。 它们提供了一种描述和解析文本的方法。 本教程将深入了解正则表达式,而不涉及任何语言的特殊性。 我们将简单地使用 egrep 来解释这些概念。

常用表达

正则表达式由两种类型的字符组成:

  • 常规文字字符和
  • 元字符

这些元字符是赋予正则表达式权力的元字符。

考虑以下 country.txt 文件,其中第一列是国家名称,第二列是国家人口,第三列是大陆。

$ cat country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Argentina,36955182,Latin America
Brazil,172860370,Latin America
Cameroon,15421937,Africa
Japan,126549976,Asia

锚元字符

我们将讨论的第一组“元字符”是 ^$^$ 分别匹配模式的开始和结束,称为 锚元字符

要找出国名以 I 开头的所有国家的名称,我们使用表达式:

$ egrep '^I' country.txt
India,1014003817,Asia
Italy,57634327,Europe

或者要找出所有大陆名称以 e 结尾的国家,我们这样做:

$ egrep 'e$' country.txt
Italy,57634327,Europe

下一个元字符是点 (.),它匹配任何 一个字符 。 要匹配国家名称正好是 5 个字符长的所有行:

$ egrep '^.....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Japan,126549976,Asia

如何查找国家名称以 I 或 J 开头且国家名称长度为 5 个字符的所有行?

$ egrep '^[IJ]....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia

[…] 被称为 字符集字符类 。 在字符集中,只有一个给定字符匹配。

字符集中的 ^ 否定字符集。 以下示例将匹配五个字符长但不以 I 或 J 开头的国家/地区名称。

$ egrep '^[^IJ]....,' country.txt
Yemen,1184300,Asia

分组元字符和交替

要匹配包含亚洲或非洲的所有行:

$ egrep 'Asia|Africa' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia

这也可以通过将 Aa 共用来完成。

$ egrep 'A(si|fric)a' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia

量词

而不是写

$ egrep '^[IJ]....,' country.txt

我们可以写

$ egrep '^[IJ].{4},' country.txt

其中 {} 被称为 量词。 他们决定了他们之前的角色应该出现多少次。

我们也可以给出一个范围:

$ egrep '^[IJ].{4,6},' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia

这将匹配以 I 或 J 开头并在其后有 4 到 6 个字符的国家/地区名称。

量词有一些可用的快捷方式。 例如,

{0,1} 等价于 ?

$ egrep '^ab{0,1}c$' filename

是相同的

$ egrep '^ab?c' filename

{0,} 等价于 *

$ egrep '^ab{0,}c$' filename

是相同的

$ egrep '^ab*c' filename

{1,} 等价于 +

$ egrep '^ab{1,}c$' filename

是相同的

$ egrep '^ab+c' filename

让我们看一些涉及我们迄今为止看到的表达式的例子。 这里不是从文件中搜索,而是从标准输入中搜索。 我们使用的技巧是我们知道 grep(或 egrep)搜索模式,如果找到模式,则显示包含该模式的整行。

我们想找出所有可能的方法来拼写句子 the gray color suit was his favourite

表达式将是:

$ egrep 'the gr[ea]y colou?r suit was his favou?rite'
the grey color suit was his favourite
the grey color suit was his favourite

the gray colour suit was his favorite
the gray colour suit was his favorite

查看上面的表达式,我们可以看到:

  • 灰色可以拼写为灰色或灰色
  • color 可以写成 color 或 color,这意味着 u 是可选的,所以我们使用 u?
  • 同样最喜欢或最喜欢的可以写为最喜欢的?

匹配美国邮政编码怎么样?

$ egrep '^[0-9]{5}(-[0-9]{4})?$'
83456
83456

83456-

834562

92456-1234
92456-1234

10344-2342-345

在 24 小时制中匹配所有有效时间的另一个示例。

$ egrep '^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]'
23:44:02
23:44:02

33:45:11

15:45:33
15:45:33

在上面的例子中,我们说过,如果小时的第一个数字是 0 或 1,那么第二个数字将是 0 到 9 之间的任何一个。 但如果第一个数字是 2,那么第二个数字的允许值为 0、1、2 或 3。

字边界

写一个图案来匹配以颜色结尾的单词,比如单色、水彩、多色等。 匹配但不是无色或彩色。 自己尝试这些示例,以熟悉它们:

$ egrep 'color\>'

接下来,要搭配无色和彩色,但不是单色、水彩、多色等。

$ egrep '\<color'

因此,为了匹配确切的单词颜色,我们这样做:

$ egrep '\<color\>'

反向引用

假设我们要匹配所有双输入的单词,例如 、thebefore ,我们必须使用反向引用。 反向引用用于记忆模式。

这是一个例子:

$ egrep "\<the\> \1"

或通用方式:

$ egrep "\<(.*)\> \1"

上面的示例可用于查找名字和姓氏相同的所有名称。 如果有不止一组括号,那么第二个,第三个第四个等等。 可以用 \2、\3、\4 等来引用。

这只是对正则表达式强大功能的介绍。