正则表达式查找包含字母排列的单词,其中一个字母是必需的,而不是任何其他字母

REGEX to find words containing permutations of letters, with one letter mandatory, and NOT any other

我们有一个 mysql table,其中有一列包含字母数字文本。我们有一个独特的用例,我们需要在 table 中找到每一行,其中此列的文本包含:

因此,这些就可以了:

SCAN
SCATTCC
NCAS 
NTTAAS

这些不行:

CATI     (does not contain S, and contains I which is outside of S, T, C, A, N) 
SCANNF   (contains F which is outside of S, T, C, A, N) 
NCASO    (contains O which is outside of S, T, C, A, N) 
..

我们尝试过类似的方法,但它不起作用:

[tacn]*[s]+(?![^stacn])+

使用此正则表达式进行模式匹配:

pattern = "^(S+[TACN]+S*[TACN]*)+$|^(S*[TACN]+S+[TACN]*)+$"

这假设 s 可以像其他允许的字符一样出现多次。这些要求没有明确排除这种可能性,尽管示例中没有包含这样的示例。我不会将 "One letter for sure" 解释为 "appears only once"。

^(s+[tacn][stacn]*|[tacn]+s[stacn]*)$

MySQL 8.0.4+

从MySQL8.0.4开始,MySQL regexp support改为ICU库,支持lookaheads。对于这些版本,此正则表达式将满足您的要求:

'^(?=.*s)(?=.*[acnt])(?!.*[^acnst])'

它使用了 3 个前瞻:

  1. (?=.*s) 断言字符串中有一个 S
  2. (?=.*[acnt]) 断言字符串中至少有一个 [ACNT]
  3. (?!.*[^acnst]) 断言字符串中除 [ACNST] 外没有其他字符。

Demo on dbfiddle

MySQL 8.0.4

之前

此正则表达式将为您提供所需的结果:

^[tacn]*(s[cant]|[tacn]s)[cant]*$

它寻找

  • 一个S,前面有零个或多个[TACN],后面有一个或多个[TACN];或
  • 一个S,前面有一个或多个[TACN],后面有零个或多个[TACN]

查询:

SELECT str, 
       str REGEXP '^[tacn]*(s[cant]|[tacn]s)[cant]*$' AS `match`
FROM test

输出:

str     match
SCAN    1
SCATTCC 1
NCAS    1
NTTAAS  1
CATI    0
SCANNF  0
NCASO   0
CANT    0
S       0
SS      0
TS      1
SC      1
STS     0

Demo on dbfiddle

如果要允许 S 出现不止一次,只需将正则表达式更改为

^[stacn]*(s[cant]|[tacn]s)[scant]*$

这会将 STS 的结果更改为 1,同时将 SS 的结果保留为 0,因为它不包含 [= 以外的字符16=].

Demo on dbfiddle