宝哥软件园

正则表达式的高级技巧和示例

编辑:宝哥软件园 来源:互联网 时间:2021-10-25

来自《粉碎杂志》的原创英语。由愚蠢的作品翻译。请指出来源。正则表达式功能强大,可以用来在一大串字符中找到所需的信息。它用常规的人物结构表达来行动。不幸的是,简单的正则表达式对于一些高级应用程序来说是不够的。如果过滤的结构复杂,您可能需要使用高级正则表达式。本文向您介绍正则表达式的高级技术。我们筛选出八个常用的概念,并举例分析。每个例子都是简单的写作,满足了一些复杂的需求。如果你不知道规律性的基本概念,请先阅读本文,或本教程,或wiki词条。这里的常规语法适用于PHP,并且与Perl兼容。

1. 贪婪/懒惰

Greed

所有可以多次限定的正则算子都是贪婪的。它们匹配尽可能多的目标字符串,这意味着匹配结果将尽可能长。不幸的是,这种做法并不总是我们想要的。因此,我们添加了“懒惰”限定词来解决这个问题。添加“?”在每个贪婪的操作符之后。让表达式只匹配尽可能短的长度。此外,修饰语“u”还可以钝化可以多次限定的操作符。理解贪婪和懒惰的区别是使用高级正则表达式的基础。00-1010运算符*与前面的表达式匹配零次或更多次。它是一个贪婪的算子。请看下面的例子:preg_match('/h1。*/h1/',' h1这是一个标题。/h1 h1这是另一个。/h1 ',$ matches);句号(。)可以表示除换行符以外的任何字符。上面的正则表达式匹配h1标签和标签中的所有内容。它使用句点(。)和星号(*),以匹配标记中的所有内容。匹配结果如下:h1这是一个标题。/h1 h1 h1这是另一个。/h1返回整个字符串。*操作员将连续匹配所有内容——,甚至包括中间的h1结束标记。因为是贪婪的,整串匹配符合利益最大化的原则。

贪婪操作符

稍微修改一下上面的公式,加上一个问号(?),这会使表达式变懒:/h1。*?/h1/所以它会觉得只需要匹配第一个h1结束标记就可以完成任务。另一个类似性质的贪婪算子是{n,}。这意味着先前的匹配模式被重复n次或更多次。如果不加问号,会寻找尽可能多的重复,如果加了,会尽量少重复(即“重复n次”最少)。#创建字符串$ str=' hihihi oops hi# match preg _ match与greedy {n,}运算符('/(hi) {2,}/',$ str,$ matches);#匹配项[0]将被“hihi hi ”#使用中止的{n,}?运算符匹配preg_match('/(hi){2,}?/',$str,$ matches);# matches[0]将为' hihi'

懒惰操作符

Back  Referencing

2. 回返引用(Back referencing)

反向引用一般翻译为“反向引用”、“反向引用”和“反向引用”。个人认为“回指”更合适。这是一种在正则表达式内部引用之前捕获内容的方法。例如,以下简单示例的目的是匹配引号内的内容:#创建匹配数组$ matches=array();#创建字符串$str=“”这是一个“字符串”;#使用正则表达式捕获内容preg_match('/('| ')。*?('|')/',$str,$ matches);#输出整个匹配字符串echo $ matches[0];它将输出:‘这是一个’。显然,这不是我们想要的。此表达式从开头的双引号开始,遇到单引号后会错误地结束匹配。这是因为表达式说:(' | '),即可以使用双引号(')和单引号(')。要解决这个问题,您可以使用退货报价。表达式 1, 2, 9是捕获的子内容的组序列号,可以作为指向这些组的“指针”来引用。在本例中,第一个匹配的引号由1表示。

有什么用?

将上面示例中的右引号替换为1: preg _ match ('/(' | ')。*?1/',$str,$ matches);这将正确返回字符串:‘这是一个‘字符串’’问题:如果是中文引号,如果前面的引号和后面的引号不是同一个字符该怎么办?还记得PHP函数preg_replace吗?还有一个退货报价。只有我们没有使用 1. 9,但使用了$1.$9 .$ n(这里可以使用任何数字)作为返回指针。例如,如果要用文本替换所有段落标签p:$ text=preg _ replace('/p(。*?)/p/'、' p$1/p '、$ html);参数$1是一个返回引用,它表示段落标签p内的文本,并被插入到替换的文本中。这种易于使用的表达写作为我们提供了一种简单的方法来获得匹配的单词,甚至可以在替换文本时使用。00-1010当一个表达式中多次使用回调引用时,很容易混淆事情。找出那些数字(1 … 9)代表哪个子内容是非常麻烦的。回调的另一种方法是使用命名的捕获组(以下称为“命名组”)。一个著名的团体使用(?Pnamepattern)来设置,名称代表组名,模式是匹配著名组的正则结构。请看下面的例子:/(?pquote“|”)。*?(?P=quote)/在上面的公式中,quote是组名,而“|”是重组匹配内容的规律性。在后面(?P=quote)是呼叫组中一个名为quote的著名组。此公式的效果与上面回调引用实例的效果相同,只是它是用命名组实现的。更容易阅读和理解吗?命名组也可用于处理匹配内容数组的内部数据。特定的常规组名也可以用作数组中匹配内容的索引词。preg_match('/(?Pquote'|')/'、' String '、$ matches);#以下语句输出" "(不包括双引号)echo $匹配项[1];#带有组名的呼叫也将输出" " echo $ matches[' quote '];因此,著名的小组不仅使编写代码变得更加容易,而且还可以用来组织代码。

如何运用?

Word  Boundaries

单词边界是单词字符(包括字母、数字和下划线,当然也包括汉字)和非单词字符在字符串中的位置。它的特别之处在于它与真实的角色不匹配。它的长度为零。b匹配所有单词边界。遗憾的是,词的界限一般被忽略,大多数人并不关心它的实际意义。比如要匹配“导入”这个词:/导入/注意!正则表达式有时很调皮。下面的字符串也可以用上面的公式成功匹配:重要你可能认为只需要在导入前后加空格就可以匹配这个独立的单词:/import/如果出现这种情况怎么办:交易者投票赞成导入当单词import在字符串的开头或结尾时,修改后的表达式仍然不能使用。所以要考虑各种情况:/(import | import | import $)/我不慌,还没完。遇到标点符号怎么办?为了满足这一个字的匹配,你可能需要write://(^import(:| |;|,)?|导入(: |;|,)?|导入(。|?|!)?$)/i只匹配一个单词有点咄咄逼人。正因为如此,词的界限意义重大。为了满足上述要求,以及许多其他变化,有了字符边界,我们只需要编写代码:/ b端口b/上述所有情况都已解决。b的灵活性在于它是一个没有长度的匹配。它只匹配两个实际角色之间的假想位置。它检查两个相邻的字符是否是单个单词,另一个是否是非单个单词。如果情况匹配,则返回匹配。如果遇到单词的开头或结尾,b将把它当作非单词字符。既然我在导入时仍然被视为一个单词字符,导入是匹配的。请注意,与b相反,我们还有B,它匹配两个单词或两个非单词之间的位置。因此,如果您想在单词内部匹配“hi”,可以使用: bhi b“this”和“hight ”,这将返回一个匹配,但“hi那边”不会返回匹配。

3. 已命名捕获组(Named Groups)

Advanced  Operators

最小分组是没有捕获的特殊正则表达式分组。通常用于提高正则表达式的性能,也用于消除特定的匹配。最小组可以使用(?模式),其中模式是匹配类型。/(?His|this)/当常规引擎匹配到最小的组时,会跳过组中标记的回溯位置。以“砸”字为例,在与上述正则表达式匹配时,正则引擎会先尝试在“砸”字中找到“他的”。显然,没有找到匹配。此时,最小组开始发挥作用:常规引擎将放弃所有回溯位置。也就是说,它不会试图从“砸”中找到“这个”。为什么要这样设置?因为“他的”没有返回匹配结果,当然,“这个”包含“他的”不能匹配!上面的例子不实用,所以我们用/t?他的?/也能达到效果。看下面的例子:/b(engineer | improve | end) b/如果用“engineering”进行匹配,常规引擎会先匹配“engineer”,但之后会遇到单词boundary, b,所以匹配不成功。然后,常规引擎会尝试在字符串中找到下一个匹配:雕刻。匹配到eng时,后一个没有再匹配,匹配失败。最后,尝试“结束”,结果也是失败。仔细观察就会发现,一旦工程师匹配失败,两者都到达字界,那么“刻”和“端”这两个字是不可能匹配成功的。这两个字比工程师短,正规的引擎不应该再做不必要的尝试。/b(?工程师|入侵|结束) b/以上替代编写方法可以节省常规引擎的匹配时间,提高代码的工作效率。

4. 字词边界(Word Boundaries)

Recursion

递归用于匹配嵌套结构,如括号嵌套、(this (that))和HTML标记嵌套divdiv/div/div。我们用(?r)来表示递归过程中的子模式。下面是匹配嵌套括号:/((?[^()] )|(?R))*)/最外面的括号“”(带反义符号)匹配嵌套结构的开头。然后是一个多选项运算符(* | *),它可以匹配除方括号外的所有字符”(?[()])”,或者通过子模式”(?r)”来再次匹配整个表达式。请注意,该运算符匹配尽可能多的嵌套。递归的另一个例子如下:/([w])。*?((?[^] )|((?R)))*/1/以上表达式综合使用了字符分组、贪婪算子、回溯和最小化分组来匹配嵌套标签。第一个括号分组([w])匹配下一个应用程序的标记名。如果您找到这个尖括号标签,请尝试找到标签内容的其余部分。下一个括号子表达式与上一个示例非常相似:要么匹配除尖括号之外的所有字符?[],或者递归匹配整个表达式(?r ).表达式末尾的/1表示封闭标签。

5. 最小组团(Atomic Groups)

Callbacks

匹配结果中的具体内容有时可能需要一些特殊的修改。为了应用多种复杂的修改,正则表达式的回调将发挥作用。回调用于动态修改函数preg_replace_callback中的字符串。您可以为preg_replace_callback指定一个函数作为参数,该函数可以接收匹配的结果数组作为参数,修改数组并将其作为替换结果返回。例如,我们希望将字符串中的所有字母都转换为大写。不幸的是,PHP没有直接转换字母大小写的常规运算符。为了完成这个任务,您可以使用常规回调。首先,表达式应该匹配所有需要大写的字母:/bw/上面的公式使用了单词边界和字符类。光有这个公式是不够的。我们还需要一个回调函数:函数upper _ case($ matches){ return strtopper($ matches[0]);}函数upper_case接收匹配结果数组,并将整个匹配结果转换为大写。在本例中,$matches[0]代表需要大写的字母。然后,我们使用preg_replace_callback实现回调:preg _ replace _ callback ('/ b w/','大写',$ str);一个简单的回调是如此强大。

6. 递归(Recursion)

Commenting

注释不用于匹配字符串,但它们是正则表达式中最重要的部分。随着常规书写越来越深、越来越复杂,推导出匹配的内容会越来越困难。在正则表达式中间添加注释是最大限度地减少未来混淆和混乱的最好方法。若要注释正则表达式,请使用(?#comment)格式。将“注释”替换为您的注释声明:/(?# Numbers) d/如果打算公开代码,注释正则表达式尤为重要。只有这样,别人才能更容易理解和修改你的代码。和其他场合的笔记一样,这也会为你重温之前写的程序提供便利。考虑使用“x”或“(?x)"修饰符来格式化注释。该修饰符允许常规引擎忽略表达式参数之间的空格。“有用”空格仍然可以用[]或s或(反义加空格)来匹配。/d #数字[]#空格 w #单词/x上面的代码与下面的公式有相同的功能:/ d(?#digit)[ ](?#空格)w(?#word)/请时刻注意代码的可读性。

7. 回调(Callbacks)

正则表达式. info关于正则表达式备忘单的综合网站信息丰富的正则表达式备忘单Regex GeneratorJ Avascript正则表达式生成器

8. 注释(Commenting)

karthik viswanathan是一个喜欢编程和做网站的高中生。你可以在他的博客上查看他的作品:横向代码。你也可以关注他的在线推特应用。

更多资讯
游戏推荐
更多+