介绍
作为系统管理员、开发人员、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 和 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)搜索模式,如果找到模式,则显示包含该模式的整行。
我们想找出所有可能的方法来拼写句子 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\>'
反向引用
假设我们要匹配所有双输入的单词,例如 、the 或 before ,我们必须使用反向引用。 反向引用用于记忆模式。
这是一个例子:
$ egrep "\<the\> \1"
或通用方式:
$ egrep "\<(.*)\> \1"
上面的示例可用于查找名字和姓氏相同的所有名称。 如果有不止一组括号,那么第二个,第三个第四个等等。 可以用 \2、\3、\4 等来引用。
这只是对正则表达式强大功能的介绍。