否定正则表达式中的特定组
Negate a specific group in regular expressions
如何获取不包含特定组的字符串?
(?:[0-9-+*/()x]|abs|pow|ln|pi|e|a?(sin|cos|tan)h?)+
以上字符串是数学表达式的正则表达式。怎么得到不是数学表达式的字符串?
示例输入字符串:WIDTH+LENGTH*abs(2)
预期输出:WIDTH
LENGTH
您可以在否定前瞻中使用正则表达式,然后添加 \w
shorthand class 来匹配字母数字符号,或者 [a-zA-Z]
与 \b
字边界:
(?![0-9-+*/()x]|abs|pow|ln|pi|e|a?(?:sin|cos|tan)h?)\b[a-zA-Z]+\b
因为我们只允许带有 [a-zA-Z]
的字母,我们可以进一步减少到
(?!x|abs|pow|ln|pi|e|a?(?:sin|cos|tan)h?)\b[a-zA-Z]+\b
虽然 在大多数情况下可能有效,但它并不是问题中正则表达式的真正反转,因为有些事情两个正则表达式都不匹配:
- 空间
- 特殊字符,例如
?!^~;:_,.[]{}<>
(可能更多)。
以及两个正则表达式做匹配的事情:
- 字符串,例如
axabs(3)
,其中 xabs
部分与两者匹配。
这可能可以通过摆弄来解决,但是该死,我想要一个 actual 反转! :P
这里是:
(?:(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)[^0-9-+*/()x])+
它是这样工作的:
- 匹配不是
0-9-+*/()x
(= [^0-9-+*/()x]
)之一的任何字符。
但不匹配那个字符,如果它匹配 preceeding/following 个字符的特定模式,并且它本身就是某个字符。
使用否定前瞻((?!...)
)意味着每个|
之后的第一个字符是当前字符,之后的字符是当前字符之后的字符,而(?<=)
是否定的向后看,匹配某些前面的字符。
所以,例如,为了不匹配sin
,我们需要"not match"s
如果后面跟着in
,不匹配i
如果前面是 s
,后面是 n
,如果前面是 si
,则不匹配 n
。
在正则表达式中(仅环视部分):(?!sin|(?<=s)in|(?<=si)n)
构建 e
、ln
、pi
等的完整列表会导致:
(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)
匹配以上一次或多次((?:...)+
).
通过将 (?<=l)n
、(?<=si)n
和 (?<=ta)n
等部分合并到 (?<=l|si|ta)n
中,正则表达式可以缩短一点:
(?:(?!e|ln|(?<=l|si|ta)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab|co)s|pow|(?<=p)ow|(?<=po)w|a?(?:sin|cos|tan)|(?<=s)in|(?<=c)os|(?<=t)an)[^0-9-+*/()x])+
可以查看此演示以及漂亮的可视化 on Debuggex。
注意 1:此正则表达式在 JavaScript 中不起作用,因为 JS-regex 不支持 lookbehind。
注意 2:在 Debuggex 中将单个多字节字符(例如 §°☀☁️❄️
)附加到测试字符串似乎会破坏它,但这不是我的正则表达式的问题,可以验证 with PHP, for example.
当你想要 "skip" 某些表达式时,这里就是你在正则表达式中所做的:
"Tarzan"|skip1|skip2|skip3|more|complicated|expressions|here|(Tarzan)
... 就像 The Best Regex Trick Ever.
一样简单
当您迭代正则表达式匹配集合时,您只需要第一个捕获组中包含任何内容的匹配,而忽略任何其他匹配。
无需使用通常不适用于重叠边缘情况的复杂环视。
如何获取不包含特定组的字符串?
(?:[0-9-+*/()x]|abs|pow|ln|pi|e|a?(sin|cos|tan)h?)+
以上字符串是数学表达式的正则表达式。怎么得到不是数学表达式的字符串?
示例输入字符串:WIDTH+LENGTH*abs(2)
预期输出:WIDTH
LENGTH
您可以在否定前瞻中使用正则表达式,然后添加 \w
shorthand class 来匹配字母数字符号,或者 [a-zA-Z]
与 \b
字边界:
(?![0-9-+*/()x]|abs|pow|ln|pi|e|a?(?:sin|cos|tan)h?)\b[a-zA-Z]+\b
因为我们只允许带有 [a-zA-Z]
的字母,我们可以进一步减少到
(?!x|abs|pow|ln|pi|e|a?(?:sin|cos|tan)h?)\b[a-zA-Z]+\b
虽然
- 空间
- 特殊字符,例如
?!^~;:_,.[]{}<>
(可能更多)。
以及两个正则表达式做匹配的事情:
- 字符串,例如
axabs(3)
,其中xabs
部分与两者匹配。
这可能可以通过摆弄来解决,但是该死,我想要一个 actual 反转! :P
这里是:
(?:(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)[^0-9-+*/()x])+
它是这样工作的:
- 匹配不是
0-9-+*/()x
(=[^0-9-+*/()x]
)之一的任何字符。 但不匹配那个字符,如果它匹配 preceeding/following 个字符的特定模式,并且它本身就是某个字符。
使用否定前瞻((?!...)
)意味着每个|
之后的第一个字符是当前字符,之后的字符是当前字符之后的字符,而(?<=)
是否定的向后看,匹配某些前面的字符。
所以,例如,为了不匹配sin
,我们需要"not match"s
如果后面跟着in
,不匹配i
如果前面是s
,后面是n
,如果前面是si
,则不匹配n
。
在正则表达式中(仅环视部分):(?!sin|(?<=s)in|(?<=si)n)
构建e
、ln
、pi
等的完整列表会导致:(?!e|ln|(?<=l)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab)s|pow|(?<=p)ow|(?<=po)w|sin|(?<=s)in|(?<=si)n|cos|(?<=c)os|(?<=co)s|tan|(?<=t)an|(?<=ta)n|asin|acos|atan)
匹配以上一次或多次(
(?:...)+
).
通过将 (?<=l)n
、(?<=si)n
和 (?<=ta)n
等部分合并到 (?<=l|si|ta)n
中,正则表达式可以缩短一点:
(?:(?!e|ln|(?<=l|si|ta)n|pi|(?<=p)i|abs|(?<=a)bs|(?<=ab|co)s|pow|(?<=p)ow|(?<=po)w|a?(?:sin|cos|tan)|(?<=s)in|(?<=c)os|(?<=t)an)[^0-9-+*/()x])+
可以查看此演示以及漂亮的可视化 on Debuggex。
注意 1:此正则表达式在 JavaScript 中不起作用,因为 JS-regex 不支持 lookbehind。
注意 2:在 Debuggex 中将单个多字节字符(例如 §°☀☁️❄️
)附加到测试字符串似乎会破坏它,但这不是我的正则表达式的问题,可以验证 with PHP, for example.
当你想要 "skip" 某些表达式时,这里就是你在正则表达式中所做的:
"Tarzan"|skip1|skip2|skip3|more|complicated|expressions|here|(Tarzan)
... 就像 The Best Regex Trick Ever.
一样简单当您迭代正则表达式匹配集合时,您只需要第一个捕获组中包含任何内容的匹配,而忽略任何其他匹配。
无需使用通常不适用于重叠边缘情况的复杂环视。