学习正则表达式

2024-10-02 12:36:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我真的不懂正则表达式。你能用简单易懂的方式向我解释一下吗?如果有任何在线工具或书籍,你也可以链接到它们吗?


Tags: tocommunityisnotitthispostedit
1条回答
网友
1楼 · 发布于 2024-10-02 12:36:38

最重要的部分是概念。一旦你了解了构建块是如何工作的,语法上的差异只不过是温和的方言而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。像Perl这样的语言消除了大部分这种复杂性,但是如果在C程序中使用正则表达式,则必须记住其他注意事项。

如果您认为正则表达式是可以随意混合和匹配的构建块,它将帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。

简单地开始

从概念上讲,最简单的正则表达式是文字字符。模式N与字符“N”匹配。

相邻的正则表达式匹配序列。例如,模式Nick匹配序列“N”,然后是“i”,然后是“c”,最后是“k”。

如果您曾经在Unix上使用过grep,即使只是为了搜索外观普通的字符串,您已经在使用正则表达式了!(在grep中的re指的是正则表达式。)

菜单上的顺序

只需添加一点复杂性,就可以将“Nick”或“Nick”与模式[Nn]ick匹配。方括号中的部分是一个字符类,这意味着它正好匹配一个封闭字符。也可以在字符类中使用范围,因此[a-c]匹配“a”或“b”或“c”。

模式.是特殊的:它与任何字符匹配,而不是仅与文本点匹配。它在概念上与真正的大字符类[-.?+%$A-Za-z0-9...]相同。

把字符类看作菜单:只选择一个。

有用的快捷方式

使用.可以节省大量的输入,还有其他一些通用模式的快捷方式。假设您想要匹配一个数字:一种编写方法是[0-9]。数字是一个频繁匹配的目标,因此您可以使用快捷方式\d。其他是\s(空白)和\w(单词字符:字母数字或下划线)。

大写变量是它们的补码,因此\S匹配任何空白字符,例如。

一次是不够的

从那里,您可以使用量词重复部分模式。例如,模式ab?c与“abc”或“ac”匹配,因为?量词使它修改的子模式成为可选的。其他量词是

  • *(零次或多次)
  • +(一次或多次)
  • {n}(精确n次)
  • {n,}(至少n次)
  • {n,m}(至少n次,但不超过m次)

把这些块放在一起,模式[Nn]*ick匹配所有

  • 点击
  • 尼克
  • 尼克
  • 恩尼克
  • 恩尼克
  • 恩尼克
  • (等等)

第一个匹配显示了一个重要的教训:*总是成功的!任何模式都可以匹配零次。

其他一些有用的例子:

  • [0-9]+(及其等价的\d+)匹配任何非负整数
  • \d{4}-\d{2}-\d{2}匹配格式类似于2019-01-01的日期

分组

量词将模式修改到其最左边。您可能希望0abc+0与“0abc0”、“0abcabc0”等匹配,但加号量词左侧的模式是c。这意味着0abc+0与“0abc0”、“0abcc0”、“0abccc0”等匹配。

要将一个或多个“abc”序列与结尾的零匹配,请使用0(abc)+0。括号表示可以量化为一个单位的子模式。正则表达式引擎保存或“捕获”与par匹配的输入文本部分也是很常见的结合基团。与计数索引和substr相比,这种方法提取位更灵活,更容易出错。

交替

早些时候,我们看到了一种匹配“Nick”或“Nick”的方法。另一种是在Nick|nick中的交替。记住,交替包括它左边的一切和它右边的一切。使用分组括号限制|的范围,例如(Nick|nick)

例如,您可以将[a-c]等价地写为a|b|c,但这可能是次优的,因为许多实现假定备选方案的长度大于1。

逃跑

虽然有些字本身是匹配的,但有些字有特殊的含义。模式\d+与反斜杠、小写D和加号不匹配:为此,我们将使用\\d\+。反斜杠删除了下列字符的特殊含义。

贪婪

正则表达式量词是贪婪的。这意味着它们尽可能多地匹配文本,同时允许整个模式成功匹配。

例如,假设输入是

"Hello," she said, "How are you?"

你可能希望".+"只匹配“Hello”,然后当你看到它从“Hello”一直匹配到“You?”时,会感到惊讶。

若要从贪心转换到您可能认为谨慎的状态,请在量词中添加一个额外的?。现在您了解了\((.+?)\),问题中的示例是如何工作的。它匹配文本左括号的序列,后跟一个或多个字符,并以右括号结尾。

如果您的输入是'(123)(456)',则第一个捕获将是'123'。非贪婪量词希望允许模式的其余部分尽快开始匹配。

(至于你的困惑,我不知道有什么正则表达式方言,((.+?))会做同样的事情。我怀疑有什么东西在传输过程中丢失了。)

使用特殊模式^只在输入的开头匹配,$只在结尾匹配。用你说的“我知道在前面和后面是什么,但是给我之间的一切”的模式做“书尾”是一个有用的技巧。

假设要匹配表单的注释

-- This is a comment --

你会写^--\s+(.+)\s+--$

建立自己的

正则表达式是递归的,因此既然您了解了这些基本规则,就可以随意组合它们。

编写和调试正则表达式的工具:

书籍

免费资源

脚注

}:以上关于.匹配任何字符的声明是出于教学目的而进行的简化,但并非严格意义上的简化。点匹配除换行符以外的任何字符,"\n",但在实践中,您很少期望像.+这样的模式跨越换行边界。Perl正则表达式有一个^{} switch和Java ^{},例如,使.完全匹配任何字符。对于没有这种特性的语言,可以使用[\s\S]之类的东西来匹配“任何空白或非空白”,换句话说就是任何东西。

相关问题 更多 >

    热门问题