正则表达式匹配模式,除非它是更大模式的一部分

时间:2018-01-10 06:40:02

标签: regex python-2.7

我需要将所有大写字母中出现的任何单词作为字符串的一部分进行标题大写,除非它们连续超过三个。

例如:

really FOO BAR foo bar

应该成为

really Foo Bar foo bar

REALLY FOO BAR FOO BAR

应保持原样。

另一个例子,Raw string:

You say goodbye but i say HELLO HELLO hello i don't know WHY YOU SAY GOODBYE I SAY HELLO.

期望的输出:

You say goodbye but i say Hello Hello hello i don't know WHY YOU SAY GOODBYE I SAY HELLO.

我尝试了类似下面的内容,但无论上下文如何,都会使用前三个空格来标记字符串。

re.sub("([A-Z]+\s? [A-Z]+\s? [A-Z]+\s?)", lambda pat: pat.group(1).title(), s)

1 个答案:

答案 0 :(得分:2)

您可以匹配3个或更多以空格分隔的大写单词的序列,并在匹配和捕获(进一步处理)所有其他大写单词时“跳过”它们。

使用以下正则表达式

\b[A-Z]+(?:\s+[A-Z]+){2,}|\b([A-Z]{2,})\b

enter image description here。请注意,如果您想避免匹配单个字词(例如I),请将+替换为{2,}(以匹配2个或更多字母)。

<强>详情

  • \b - 字边界
  • [A-Z]+ - 1+ ASCII大写字母
  • (?:\s+[A-Z]+){2,} - 出现2次或更多次1+空格字符,后跟1 + ASCII大写字母(将+替换为{2,}以匹配2个或更多字母)
  • | - 或
  • \b([A-Z]{2,})\b - 由2个或更多ASCII大写字母组成的整个单词。

its demo online,代码看起来像

import re
s='really FOO BAR foo bar and REALLY FOO BAR FOO BAR'
rx = r'\b[A-Z]+(?:\s+[A-Z]+){2,}|\b([A-Z]{2,})\b'
res = re.sub(rx, lambda pat: pat.group(1).title() if pat.group(1) else pat.group(), s)
print(res) # => really Foo Bar foo bar and REALLY FOO BAR FOO BAR

pat.group(1).title() if pat.group(1) else pat.group()表示仅当匹配时才会标记第1组值,否则将整个匹配粘贴回未处理。