PHP 正则表达式:删除不完全等于 3 个字符的单词

PHP Regex: Remove words not equal exactly 3 characters

出色的“非常接近”答案位于 Remove words less than 3 chars DEMO 其中正则表达式

\b([a-z]{1,2})\b

删除所有少于 3 个字符的词。

但是如何重置此演示反之亦然?删除所有不完全等于 3 个字符的单词? 我们可以通过

准确地捕捉到 3 个字符的单词
\b([a-z]{3})\b

但是如何告诉正则表达式 - 删除所有其他不等于 3 的词?

所以在上面的正则表达式演示参考中应该只留下单词 'and'

使用备选方案匹配 1-2 或 4 个以上的字母。

\b(?:[a-z]{1,2}|[a-z]{4,})\b

我想也许:

\b(?![a-z]{3}\b)[a-z]+\b

匹配:

  • \b - 单词边界。
  • (?![a-z]{3}\b) - 避免三字母单词的否定前瞻。
  • [a-z]+\b - 任何 1+ 字母词(贪心)我们到词边界。

另一个技巧是使用捕获组来匹配你想要的:

\b(?:[a-z]{3}|([a-z]+))\b
  • \b - 单词边界
  • (?:[a-z]{3}|([a-z]+)) - 交替内的嵌套捕获组首先忽略三个字母字符并捕获任何 1+ 个单词(贪婪)。
  • \b - 单词边界

具有至少 2 个字符和所有格量词的可选字母组:

\b[a-z]{1,2}+(?:[a-z]{2,})?\b

demo

这种方法基于计算技巧和回溯。
换句话说:2 + x = 3 且 x > 1 无解。

如果我写了 \b[a-z]{1,2}(?:[a-z]{2,})?\b(有或没有最后一个 \b 并不重要),当正则表达式引擎到达三个字母单词开头的位置时 [a-z]{1,2} 会消耗前两个字母,但由于最后一个单词边界需要一个额外的字符才能成功,正则表达式引擎没有其他选择来回溯 {1,2} 量词。通过一个回溯步骤,[a-z]{1,2} 将只消耗一个字符,而 (?:[a-z]{2,})?\b 可能会成功。但是通过使这个量词具有所有格,我禁止了这个回溯步骤。因为对于三个字母的单词,[a-z]{1,2}+ 需要 2 个字符而 [a-z]{2,} 至少需要 2 个字母,所以模式失败。


使用词边界并用所有格量词强制失败:

\b(?:[a-z]{3}\b)?+[a-z]+

demo

这个也玩了一个不可能的断言:三个字母后跟一个单词边界,后面不能跟一个字母

再来一次,三个字母的单词,一旦三个字母被[a-z]{3}消耗掉,所有格量词?+禁止回溯,[a-z]+使模式失效。


用 3 个字母强制失败并使用回溯控制动词跳过它们:

\b[a-z]{3}\b(*SKIP)^|[a-z]+

demo

另一种具有负后视断言左侧不是 3 个字符的变体

\b[a-z]+\b(?<!\b[a-z][a-z][a-z]\b)

Regex demo

或者对 3 个字符 a-z 使用跳过失败方法:

\b[a-z]{3}\b(*SKIP)(*F)|\b[a-z]+\b

Regex demo