在 python 中使用 re.findall 时,如何将 `?` 应用于两个子表达式的组合?

How to apply `?` on combination of two sub expressions when using re.findall in python?

我想return所有以字母或数字开头和结尾的单词。它们最多可以包含一个句点 . 或连字符 -。 因此,ab.ab 有效,但 ab. 无效。

import re
reg = r"[\d\w]+([-.][\d\w]+)?"
s = "sample text"
print(re.findall(reg, s))

由于括号的缘故,它不起作用。如何在 [-.][\d\w]+

的组合上应用 ?

改成非捕获组,这样就不会有任何捕获组,这将确保完整匹配被 re.findall:

捕获
reg = r"[\d\w]+(?:[-.][\d\w]+)?"

当然,不做群攻。使用 (?:pattern) 而不是 (pattern):

import re
reg = r"[\d\w]+(?:[-.][\d\w]+)?"
s = "sample text"
print(re.findall(reg, s))

输出:

['sample', 'text']

如果 ab. 无效且不应匹配,并且句点或连字符不应位于开头或结尾,您可以匹配一个或多个数字或字符后跟匹配点或连字符后跟一个或多个数字或字符的可选部分。

(?<!\S)[a-zA-Z\d]+(?:[.-][a-zA-Z\d]+)?(?!\S)

Regex demo

说明

  • (?<!\S) 断言左侧不是非空白字符的否定回顾
  • [a-zA-Z\d]+ 匹配一个或多个lower/uppercase字符或数字
  • (?:[.-][a-zA-Z\d]+)? 一个可选的非捕获组,它将匹配一个点或一个连字符,后跟一个或更多次 lower/uppercase 字符或一个数字
  • (?!\S 断言右边的内容不是非空白字符的否定前瞻。

Python demo