介绍
注意:请 访问此配套教程,详细了解如何使用grep
正则表达式在 Linux 中搜索文本模式。
作为系统管理员、开发人员、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
这也可以通过取A和一个公共来完成。
$ 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)搜索模式,如果找到模式,则显示包含该模式的整行。
我们想找出所有可能的拼写方法“灰色西装是他最喜欢的”。
表达式为:
$ 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
查看上面的表达式,我们可以看到:
-
灰色可以拼写为灰色或灰色
-
颜色可以写成颜色或颜色,这意味着 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\>'
反向引用
假设我们要匹配所有双输入的单词,例如the或before,我们必须使用反向引用。反向引用用于记住模式。
下面是一个例子:
$ egrep "\<the\> "
或通用方式:
$ egrep "\<(.*)\> "
上面的例子可以用来查找所有名字和姓氏相同的名字。如果有不止一组括号,那么第二个、第三个、第四个等可以用\2、\3、\4等引用。
这只是对正则表达式功能的介绍。