正则表达式查找包含字母排列的单词,其中一个字母是必需的,而不是任何其他字母
REGEX to find words containing permutations of letters, with one letter mandatory, and NOT any other
我们有一个 mysql table,其中有一列包含字母数字文本。我们有一个独特的用例,我们需要在 table 中找到每一行,其中此列的文本包含:
- 肯定是一个字母,比如S
- 再加上其他几个字母中的一个或多个,比如T、A、C、N(字母可以有顺序,重复多少次)
- 除了 S 和 T、A、C、N 之外,不包含任何其他字母
因此,这些就可以了:
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 个前瞻:
(?=.*s)
断言字符串中有一个 S
;
(?=.*[acnt])
断言字符串中至少有一个 [ACNT]
;
(?!.*[^acnst])
断言字符串中除 [ACNST]
外没有其他字符。
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
如果要允许 S
出现不止一次,只需将正则表达式更改为
^[stacn]*(s[cant]|[tacn]s)[scant]*$
这会将 STS
的结果更改为 1
,同时将 SS
的结果保留为 0
,因为它不包含 [= 以外的字符16=].
我们有一个 mysql table,其中有一列包含字母数字文本。我们有一个独特的用例,我们需要在 table 中找到每一行,其中此列的文本包含:
- 肯定是一个字母,比如S
- 再加上其他几个字母中的一个或多个,比如T、A、C、N(字母可以有顺序,重复多少次)
- 除了 S 和 T、A、C、N 之外,不包含任何其他字母
因此,这些就可以了:
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 个前瞻:
(?=.*s)
断言字符串中有一个S
;(?=.*[acnt])
断言字符串中至少有一个[ACNT]
;(?!.*[^acnst])
断言字符串中除[ACNST]
外没有其他字符。
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
如果要允许 S
出现不止一次,只需将正则表达式更改为
^[stacn]*(s[cant]|[tacn]s)[scant]*$
这会将 STS
的结果更改为 1
,同时将 SS
的结果保留为 0
,因为它不包含 [= 以外的字符16=].