快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

和记娱h188下载app:磨练构建正则表达式模式的技能



经由过程本文的进修,您可以增添一些有用的设计实际正则表达式 (regexp) 的技能。构建正则表达式是任何治理员日常事情中的一部分。为了构造返回所需前提的成功正则表达式,必要进修以模式匹配的角度进行思虑,而这种技能必要花大年夜量的光阴进行演习。

小序

UNIX® 治理员天天都必要构建和应用正则表达式 (regexp) 进行文本模式匹配。大年夜多半说话都支持正则表达式的某种实现。有的利用法度榜样(如 EMACS)具有正则表达式搜索功能,并且您可以经由过程各类敕令行对象应用正则表达式。无论什么利用法度榜样,构建精确的正则表达式的关键之处在于,识别仅满意必要匹配的数据的模式,以便在输入中扫除其他不需要的内容。

出于这个目的,本文将慢慢先容几种正则表达式模式构建技术,并先容它们若何赞助您完成各类老例义务。

应用正则表达式 (regexp)

除非分外阐明,否则本文中应用的示例都是扩展可移植操作系统接口(扩展 POSIX)的正则表达式。假如经由过程敕令行(如应用 egrep 实用对象)应用它们,您应该根据必要引用各类正则表达式。请记着,不合的正则表达式实现之间存在一些差别,您可能不得不适应所应用的特定的对象、利用法度榜样或说话中的详细实现。

匹配整行内容

^ 元字符匹配行首,而 $ 匹配行尾,假如将它们组和记娱h188下载app合在一路(如 ^$),它们将匹配空行。(这个表达式的镜像,即 $^,是弗成能匹配成功的,它将永世 都无法匹配到有效行。)这个基础的正则表达式是许多繁杂正则表达式的根基,假如您还不习气应用这个基础的正则表达式,那么您应该慢慢养成应用它的习气。应用它来构建匹配整行内容 的模式。

在用户字典文件 (/usr/dict/words) 中搜索是一个很好的基础模式。(有些版本的 UNIX 将用户字典放在 /usr/share/dict/words 中。)

例如,假设您忘怀了若何拼写单词 fuchsia。此中是否包孕 sh 或 cs 呢?您所知道的只是,它以 fu 开首并以 ia 结尾。

考试测验应用这个模式进行搜索:

$ egrep -i '^fu.*ia$' /usr/dict/words

-i 标志表示在搜索历程中不区分大年夜小写。在这个示例中,由于 fuchsia 拼写精确,以是在返回的单词中包括这个单词。

根据长度匹配行

应用大年夜括号元字符 ({ }) 指定前面的正则表达式匹配若干次,如表 1 所示。当您将它们添加到刚才先容的整行搜索中时,您可以指定行的长度。

表 1. 大年夜括号元字符的含义

示例描述

{X}

这个字符对前面的正则表达式匹配 X 次。

{X,}

这个字符对前面的正则表达式匹配 X 或更多 次。

{X,Y}

这个字符对前面的正则表达式匹配至少 X 而不跨越 Y 次。

并不是所有扩展正则表达式的实现都支持大年夜括号。此外,根据详细的实现,您可能必要先应用反斜杠对其进行转义。

您可以应用这个正则表达式获得字典中以单词长度为顺序的申报。所得到结果的数目取决于本地系统的字典文件中单词的数目,然而,它应该与清单 1 所示类似。在这个示例中,最常见的单词长度是 9 个字母,该字典中有 32,380 个匹配单词。该字典中不包括 25 个字母或更长的单词,并且最长的单词并不是您觉得的 21 个字母长的 disestablishmentarian(有 81 个同样长度的单词,包括 superincomprehensible 和 phoneticohieroglyphic),这个 UNIX 字典中最长的单词有 5 个,包括 pathologicopsychological。和记娱h188下载app

清单 1. 谋略字典中 X 个字母的单词的个数

$ for i in `seq 1 32`

> {

>  echo "There are" `egrep '^.{'$i'}$' /usr/dict/words \

| wc -l` "$i-letter words in the dictionary."

> }

There are 52 1-letter words in the dictionary.

There are 155 2-letter words in the dictionary.

There are 1351 3-letter words in the dictionary.

There are 5110 4-letter words in the dictionary.

There are 9987 5-letter words in the dictionary.

There are 17477 6-letter words in the dictionary.

There are 23734 7-letter words in the dictionary.

There are 29926 8-letter words in the dictionary.

There are 32380 9-letter words in the dictionary.

There are 30867 10-letter words in the dictionary.

There are 26011 11-letter words in the dictionary.

There are 20460 12-letter words in the dictionary.

There are 14938 13-letter words in the dictionary.

There are 9762 14-letter words in the dictionary.

There are 5924 15-letter words in the dictionary.

There are 3377 16-letter words in the dictionary.

There are 1813 17-letter words in the dictionary.

There are 842 18-letter words in the dictionary.

There are 428 19-letter words in the dictionary.

There are 198 20-letter words in the dictionary.

There are 82 21-letter words in the dictionary.

There are 41 22-letter words in the dictionary.

There are 17 23-letter words in the dictionary.

There are 5 24-letter words in the dictionary.

There are 0 25-letter words in the dictionary.

There are 0 26-letter words in the dictionary.

There are 0 27-和记娱h188下载appletter words in the dictionary.

There are 0 28-letter words in the dictionary.

There are 0 29-letter words in the dictionary.

There are 0 30-letter words in the dictionary.

There are 0 31-letter words in the dictionary.

There are 0 32-letter words in the dictionary.

$

匹配单词

环抱字符 \ 是异常有用的模式构造器:它们将要匹配的全部单词 括起来,这表示,它们不会匹配带括号的模式,除非该模式本身便是一个单词。单词 定义为两侧由非单词字符描述的、随意率性数目组成单词的字符(数字、字母和下划线字符)。非单词字符包括下面的所有字符:

行首

空缺字符

标点符号

行尾

任何除字母、数字或下划线以外的字符

这些环抱字符可以节省大年夜量的光阴,然则它们经常没有被充分地使用,可能是由于并非所有的正则表达式实现都支持它们。假如您的正则表达式实现支持它们,那么您应该慢慢养成应用它们的习气。

将必要零丁匹配的单词括起来,如下所示:

\

这个示例中的正则表达式不会匹配单词 ecosystem、systemic 或 system/70,也不会匹配模式 system 呈现在行中随意率性位置的那些行,它将仅仅 匹配 system 作为自力的单词呈现的那些行。

环抱字符与圆括号中的分组结合在一路,可以用来匹配部分 单词。

要匹配包孕以 pre 开首 的单词的那些行,可以应用:

\

前面的示例将匹配包孕单词 preface 和 preposterous 的行,但不会匹配 spread 或 Dupre。

匹配重复单词

这里先容一种应用单词环抱字符匹配重复单词的快速措施,重复单词表示一个单词在空格之后再次呈现。您还可以应用逆向引用,这是大年夜多半盛行的正则表达式实现中的一种递归特点,它可以匹配模式本身的某一部分。(将模式中必要引用的部分应用圆括号括起来,然后应用反斜杠加上必要进行引用的环抱字符编号来调用逆向引用:1 表示第一个圆括号分组,2 表示第二个圆括号分组,依此类推。)

要查找重复的单词,搜索在随意率性数目的空格之后再次呈现该单词的环境,可以经由过程对第一个应用圆括号的部分进行逆向引用来实现:

(\)( )+\1

这个示例匹配缩写形式和任何类型的单词,然则它不会匹配由标点符号分隔的重复单词,如 It's been a long, long time。

要匹配所有的重复单词,包括由空格和 随意率性标点符号分隔的重复单词,可以应用下面的表达式:

(\).?( )+\1

假如必要对这些正则表达式应用 grep,则务必应用 -i 标志,以便在搜索中不区分大年夜小写。

匹配小时

让我们再来看别的一类常见的问题:光阴和日期。这里先容了一些设计匹配精确模式的正则表达式所必要斟酌的事变。

您无法搜索任何两位的数字来匹配分钟和秒,由于它们仅仅是从 0 到 59,要匹配它们,您必要应用方括号将表示十位和个位的范围括起来:

要匹配标准的 12 或 24 小时款式的小时,可以应用下面的表达式:

(([0-1]?[0-9])|([2][0-3])):([0-5][0-9])(:[0-5][0-9])?

要匹配 12 小时 AM/PM 款式、带或不带秒数的光阴,以致匹配大年夜写或小写、和记娱h188下载app不带后缀 AM 或 PM 标识符的光阴,可以应用下面的表达式:

([^0-9])([0-1]?[0-9]){1}(((:([0-5]){1}([0-9]){1}){1,2})|(( )?([AP]M)|([ap]m)))?

假如在上一个示例中没有开始的否定语句,它将匹配不带冒号的光阴,这将取决于输入数据,可能会匹配中波广播电台(在美国称为调幅 AM 电台),如 1450 AM。

匹配月份

匹配 12 个月中的任何月份必要一个应用 | 操作符进行分隔的列表,但无意偶尔会应用不合的要领对日期进行缩写:

要查找完备拼写或三字母缩写的 12 个月份,可以应用下面的表达式(位于一行):

Jan(uary)?|Feb(uary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|

Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?

您可以加以想象并搜索完备拼写或三字母缩写的变形,即仅当后面紧随着一个空格或点号的环境,可以应用下面的表达式(位于一行):

Jan(uary| |\.)|Feb(uary| |\.)|Mar(ch| |\.)|Apr(il| |\.)|May( |\.)|Jun(e| |\.)|Jul(y| |\

.)|Aug(ust| |\.)|Sep(tember| |\.)|Oct(ober| |\.)|Nov(ember| |\.)|Dec(ember| |\.)

请留意,在上面的这两个示例中,May 是一个特殊的例外。在所有的月份中,它是独一的完备拼写与三字母缩写相同的月份,以是成功的匹配必须包孕这两种变形中的任何一种 作为其缩写,是以像“Mayflower”这样的单词不会导致误报。

当匹配模式前面的字符不是空格或行首时,这些示例照样会掉败(返回误报的结果)。这不太可能会呈现在英语散文中,然则可能呈现在法度榜样源代码中,由于此中可能应用了像 NumOct 这样的变量名。

要修复这些问题,可以履行下面的操作:

应用圆括号将全部正则表达式括起来,并在它的前面加上另一个限制符,用于匹配行首或者空格字符,如下所示(位于一行):

(^| )(Jan(uary| |\.)|Feb(uary| |\.)|Mar(ch| |\.)|Apr(il| |\.)|

May( |\.)|Jun(e| |\.)|Jul(y| |\.)|Aug(ust| |\.)|Sep(tember| |

\.)|Oct(ober| |\.)|Nov(ember| |\.)|Dec(ember| |\.))

另一种完成这个义务的措施是,在该正则表达式的前面加上一个限制符,以匹配非翰墨数字的字符,如下所示(位于一行):

([^A-Za-z0-9])(Jan(uary| |\.)|Feb(uary| |\.)|Mar(ch| |\.)|

Apr(il| |\.)|May( |\.)|Jun(e| |\.)|Jul(y| |\.)|Aug(ust| |\.)|

Sep(tember| |\.)|Oct(ober| |\.)|Nov(ember| |\.)|Dec(ember| |\.))

然则仍旧存在潜在的问题,对付搜索整篇英文散文,这些示例并弗成靠,由于它们可能返回差错的匹配结果,如“Janelle”或“Augury”这样的单词。要修复这个问题,您必须应用单词环抱字符将每个月份括起来。

本文开首提到,精确的正则表达式应该仅返回必要匹配的数据,以便在输入中扫除其他不需要的内容。这种措词是颠末仔细斟酌的,由于对付构建正则表达式来说,这与高低文有关。对付有些环境,前面的示例异常得当,无需添加额外的单词环抱字符。在其他的环境下,可以对其进行相称程度的简化,例如,假如您正在搜索仅包孕大年夜写的日期数值数据的日志文件,那么只必要应用像 [A-S] 这样的正则表达式来匹配包孕月份名称的行。

匹配日期

您可以结合一些表 1 所示的数量匹配来匹配日期。

要匹配“month, day, years”,可以应用下面的正则表达式(由于撇号字符是该正则表达式的一部分,以是必须应用双引号将它括起来,如下所示):

"[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2})"

这个正则表达式匹配 9 种不合的日期款式:

MONTH [D]D, YY

MONTH [D]D, 'YY

MONTH [D]D, YYYY

MON. [D]D, YY

MON. [D]D, 'YY

MON. [D]D, YYYY

MON [D]D, YY

MON [D]D, 'YY

MON [D]D, YYYY

这个正则表达式的误报包括“Order 99, 99”,要打消这些误报,可以将这个正则表达式与用于月份的正则表达式结合起来,如上所述,以便能够仅匹配实际的月份名称。别的,变动数值范围以避免差错的匹配,并且经由过程使逗号成为可选项,重复了 18 种可能的款式。

这将获得一个很长的正则表达式。考试测验下面的表达式:

"([^A-Za-z0-9])(Jan(uary| |\.)|Feb(uary| |\.)|Mar(ch| |\.)|

Apr(il| |\.)|May( |\.)|Jun(e| |\.)|Jul(y| |\.)|Aug(ust| |\.)|

Sep(tember| |\.)|Oct(ober| |\.)|Nov(ember| |\.)|

Dec(ember| |\.)) [0-3]?[0-9]{1}(,)? ([0-9]{4}|'?[0-9]{2})"

同样,根据您的必要仔细设计正则表达式。匹配模式平日对照轻易,这是由于它存在于特定输入的高低文中,而不是由于它可能自力于数据集而存在。后代人将会发明,前面那个很长的正则表达式中仍旧存在 Y10K 差错,由于它能匹配的最大年夜可能的年份为 9999。

匹配整数

正如您在前几个示例中看到的,应用方括号中的范围可以很好地匹配数值。

要匹配随意率性长度的整数,可以在数值范围后面加上 +;要包括负值,可以在它的前面加上可选的负号(连字号)匹配:

-?[0-9]+

前面的例子可以匹配 0,由于 0 是指定范围中可选的字符。

对付数值匹配,应用圆括号将某些部分括起来也异常有效。要匹配随意率性的十进制数值,可以应用包孕小数点加上一个或多个数值的可选环抱字符,以此对前面的正则表达式进行扩展:

-?[0-9]+(\.[0-9]+)?

可以应用方括号指定十进制数值的小数位数。例如,要匹配小数位数为 5 或更多小数位数的正数值,可以应用下面的表达式:

[^-][0-9]+\.([0-9]){5,}

更多实际的匹配

范围加上应用括号括起来的元字符,在查找相符任何特定款式的数值时异常有用。将前面先容的一些技巧结合起来,可以构建匹配各类数据的正则表达式:

要匹配美国的电话号码,可以应用:

((\([2-9][0-9]{2}\))?\ ?|[2-9][0-9]{2}(?:\-?|\ ?))[2-9][0-9]{2}[- ]?[0-9]{4}

这个正则表达式可以匹配美国 15 种款式的电话号码:

(NPA) PRE-SUFF

(NPA) PRE SUFF

(NPA) PRESUFF

(NPA)PRE-SUFF

(NPA)PRE SUFF

(NPA)PRESUFF

NPA PRE-SUFF

NPA PRE SUFF

NPA PRESUFF

N和记娱h188下载appPAPRE-SUFF

NPAPRE SUFF

NPAPRESUFF

PRE-SUFF

PRE SUFF

PRESUFF

它还可以匹配美国免费 WATS 号码,只管 1-800 的“1-”前缀或其他的免费号码不是匹配的一部分,但它本身可以匹配 10 位的数值。对付以 1 或 1+ 开首的美国号码和随意率性数目的空格,也完全一样,长途电话拨号前缀本身无法匹配,然则只要它后面随实在际的号码,这个正则表达式就能够将其找出来。

要匹配两或三位域的电子邮件地址,可以考试测验下面的表达式:

\@[a-zA-Z_\.]+?\.[a-zA-Z]{2,3}

要匹配如今所有盛行的 URL,可以应用下面的正则表达式:

(((http(s)?|ftp|telnet|news)://|mailto:)[^\(\)[:space:]]+)

这个表达式可以正常运行,然则匹配 URL 并不像您想象的那么简单。匹配任何可能的 URL 的正则表达式,如 RFC 1738 中的定义,颁发在“Regexp for URLs”(请拜见参考资料部分)一文中,它异常伟大年夜并且看起来令人生畏。现在应该将它合并为一个 [:url:] 类(假如有用于处置惩罚类似数据种类的各类新的类,如 [:email:],那就好了)。

停止语

本文涉及到一些用于编写正则表达式的模式构建技巧,以及若何应用它们来完成治理员时常碰着的特定类型数据匹配的事情。在此历程中,向您先容了大年夜量有代价的实际正则表达式,您可以将它们添加到自己的治理对象库中。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

您可能还会对下面的文章感兴趣: