字边界由\b 给出,因此以下正则表达式匹配以ing 或s 结尾的字:"\b(\w+?(?:ing|s))\b" 其中\b 是字边界,\w+ 是一个或多个“字字符”和@987654330 @ 是 ing 或 s 的未捕获组。
正如你问“如何开发正则表达式”:
首先:不要将正则表达式用于复杂的任务。它们很难阅读、编写和维护。例如有a regex that validates email addresses - 但它是由计算机生成的,你不应该在实践中使用任何东西。
从简单开始并添加边缘案例。一开始就计划你需要使用哪些字符:你说你需要以s或ing结尾的单词。所以你可能需要一些东西来表示一个单词、单词的结尾和文字字符s 和ing。什么是词?这可能会因情况而异,但至少每个字母字符都是如此。在python documentation on regexes中查找可以找到\w,即[a-zA-Z0-9_],很符合我对一个单词字符的印象。在那里您还可以找到\b,这是一个单词边界。
所以“第一个伪代码尝试”类似于\b\w...\w\b,它匹配一个单词。我们仍然需要“形式化”...,我们希望它具有“一个或多个字符”的含义,直接翻译为\b\w+\b。我们现在可以匹配一个单词!我们仍然需要s 或ing。 | 转换为或,那么以下内容如何:\b\w+ing|s\b?如果你对此进行测试,你会发现它会匹配像 ingest 这样不应该匹配我们的正则表达式的令人困惑的东西。怎么了?您可能已经看到| 无法知道“它应该或”,所以我们需要引入括号:\b\w+(ing|s)\b。恭喜,您现在已经获得了一个有效的正则表达式!
为什么(以及如何)这与我首先给出的示例不同?首先我写了\w+? 而不是\w+,? 将+ 变成了非贪婪版本。如果您知道贪婪和非贪婪之间的区别是什么,请跳过本段。考虑以下内容:AaAAbA,我们想要匹配用大字母 A 括起来的东西。一个天真的尝试:A\w+A,所以一个或多个单词字符用A 括起来。这匹配AaA,但也匹配AaAAbA,A 仍然可以匹配\w。在没有进一步配置的情况下,*+? 量词都尝试尽可能地匹配。有时,就像在 A 示例中一样,您不希望这样,然后您可以在量词后使用 ? 来表示您想要一个非贪婪版本,即尽可能少匹配的版本。
但在我们的例子中,这不是必需的,单词被空格很好地分隔,这不是\w 的一部分。所以事实上你可以让+变得贪婪,一切都会好起来的。如果您使用.(任何字符),您通常需要注意不要匹配太多。
另一个区别是使用(?:s|ing) 而不是(s|ing)。 ?: 在这里做什么?它将捕获组更改为非捕获组。通常,您不想从正则表达式中获得“一切”。考虑以下正则表达式:I want to go to \w+。您对整个句子不感兴趣,而只对\w+ 感兴趣,因此您可以将其捕获在一个组中:I want to go to (\w+)。这意味着您对此特定信息感兴趣并希望稍后检索它。有时(例如使用| 时)您需要将表达式组合在一起,但对它们的内容不感兴趣,然后您可以将其声明为非捕获。否则你会得到这个组(s 或 ing),但不是真正的单词!
总结一下:
* 从小处着手
* 一个接一个地添加一个案例
* 总是用例子来测试
实际上我只是尝试了re.findall(\b\w+(?:ing|s)\b, "fishing words"),但没有成功。 \w+(?:ing|s) 有效。我不知道为什么,也许其他人可以解释一下。正则表达式是一种神秘的东西,只能将它们用于简单且易于测试的任务。