如何将任何正则表达式变成其自身的补充而无需复杂的手动编辑?
以下是伪示例,不是真正的正则表达式,但仍然是我的意思的示例:
.* (anything)
-.* (NOT anything)
[A-Z] (Any letter A to Z, caps only)
-[A-Z] (NOT any letter A to Z, caps only)
编辑:将问题中的逆改为补。这是进行更改的地方:“将任何正则表达式变成其自身的补充”
The following are pseudo examples, not real regex, but still an example of what I mean:
.* (anything)
-.* (NOT anything)
[A-Z] (Any letter A to Z, caps only)
-[A-Z] (NOT any letter A to Z, caps only)
EDIT: Changed inverse into complement in the question. Here's where the change was made: "turn any regex into an complement of itself "
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
首先,我相信你的意思是正则表达式的补,而不是它的逆。正则表达式的逆没有多大意义;但如果将其视为一个函数,我想您可以说匹配器的逆是生成所有匹配字符串或其他内容的生成器。另一方面,一种语言的补语是所有那些非原始语言中的字符串。
那么,这里有两个观点需要考虑:
从根本上来说,
正则语言的补集是正则的。这意味着可以为补集生成接受 DFA(实际上,这样做非常简单:只需将非接受状态集与接受状态集交换即可)。任何这样的 DFA 都可以表示为正则表达式 - 所以原则上你确实可以制作这样的正则表达式。
请参阅关于常规语言的维基百科文章作为起点。
实际上,
当今大多数现代语言中使用的典型 Perl 兼容正则表达式语法没有补码运算符。对于完整正则表达式,您可以通过使用否定先行运算符得到类似的结果:
(?!X)
将在X
时精确匹配字符串不会。然而,这是补码运算符的一个糟糕的替代品,因为您将无法以通常的方式将它用作更大的正则表达式的一部分;该正则表达式不会“消耗”输入,这意味着它与其他运算符结合使用时表现不同。例如,如果您将数字字符串匹配为
[0-9]*
,则要匹配整个字符串,您需要在前面添加^
并附加$
,但要使用这种技术来查找补集,您需要编写^(?!^[0-9]*$).*$
- 这种否定正则表达式的通常串联是,据我所知,不可撤销。有点讽刺的是,由于反向引用,正则表达式的实际化身在理论上更加强大,但实际上却不太灵活,因为该语言无法轻松表达补码和交集运算。
First of all, I believe you mean the complement of a regular expression, not it's inverse. The inverse of a regular expression doesn't make much sense; but if viewed as a function, I suppose you could say that the inverse of the matcher is the generator which generates all matching strings - or something. On the other hand, the complement of a language is all those strings not in the original language.
Then, there are two views to consider here:
Fundamentally
The complement of a regular language is regular. That means it's possible to generate an accepting DFA for the complement (and doing so is very simple, actually: just swap the non-accepting state set with the accepting state set). Any such DFA can be expressed as a regular expression - so in principle you can indeed make such a regex.
See the wikipedia article on Regular Languages as a starting point.
Practically
The typical perl-compatible regex syntax used in most modern languages nowadays does not have a complementation operator. For a complete regex, you can get something similar by using the negative lookahead operator:
(?!X)
will match a string precisely whenX
will not. However, this is a poor replacement for complement operator as you will not be able to use it as a part of a larger regex in the usual fashion; this regex doesn't "consume" input which means it behaves differently in conjunction with other operators.For example, if you match numeric strings as
[0-9]*
, to match the entire string you'd prepend^
and append$
, but to use this technique to find the complement you'd need to write^(?!^[0-9]*$).*$
- and the usual concatenation of such a negated regex is, as far as I can tell, undoable.Somewhat ironically, the practical incarnation of regexes is theoretically more powerful due to backreferences, but practically less flexible since the language can't quite express the complement and intersection operations easily.
只需运行正则表达式并逻辑反转输出即可。因此更改
为:
字符类可以用前导克拉反转:
[AZ] -> [^AZ]
如果您将说明符大写,许多特殊字符也有反义字符。
Just run the regex and logically invert the output. So change:
to:
Character classes can be inverted with a leading carat:
[A-Z] -> [^A-Z]
A lot of the special characters have inverses, too, if you capitalize the specifier.
需要考虑的几种变体:
匹配由特定字符集组成的字符串:
^[az]*$
匹配由除了特定字符集之外的任何内容组成的字符串:
^[^az]*$
请注意,有一些快捷键:
\w
:任何字母数字字符(包括_
)、\W
:任何非字母数字字符;\s
:任何空白字符,\S
:任何非空白字符,\d
:任何数字,\D:任何非数字。
这可能会变得非常复杂,例如,如果您想要...
[\d_\W]
,或[^\d_\W]
(即“不是数字,不是_
,也不是非字母数字字符)匹配包含子字符串的字符串:
^.*substring.*$
匹配不包含子字符串的字符串:
^(?:(?!substring).)*$
请注意我们如何检查字符串中的每个位置是否有“子字符串的不存在”。您还可以用任何正则表达式替换
substring
来匹配包含或不包含特定子正则表达式的字符串。匹配任何内容:
.*
(如果你还想匹配换行符,你必须设置你的编程语言的相应选项,例如Python中的re.DOTALL
)如果你不知道如何设置,则匹配任何内容选项:
[\s\S]*
从不匹配任何内容(无论出于何种原因):
$^
(即匹配之前的字符串结尾字符串的开头)、\b\B
(匹配同时存在单词边界和非单词边界的位置)或(?!)
(匹配不可能匹配空字符串的位置)。Several variations to consider:
Match a string that consists of a certain set of characters:
^[a-z]*$
Match a string that consists of anything but a certain set of characters:
^[^a-z]*$
Note that there are some shortcuts:
\w
: any alphanumeric character (including_
),\W
: any non-alphanumeric character;\s
: any whitespace character,\S
: any non-whitespace character,\d
: any digit,\D
: any non-digit.This can get quite complicated, for example if you want...
[\d_\W]
, or[^\d_\W]
(i. e. "not a digit, not a_
, and not a non-alphanumeric character)Match a string that contains a substring:
^.*substring.*$
Match a string that does not contain a substring:
^(?:(?!substring).)*$
Note how we have to check each position in the string for the "not-presence" of the substring. You can also substitute any regex for
substring
to match strings that contain or don't contain a certain sub-regex.Match anything:
.*
(if you want to also match newlines, you'll have to set the corresponding option of your programming language, e. g.re.DOTALL
in Python)Match anything if you don't know how to set that option:
[\s\S]*
Never match anything (for whatever reason):
$^
(i. e. match the end of the string before the start of the string),\b\B
(match a position where there is at the same time a word boundary and not a word boundary) or(?!)
(match a position where it's impossible to match the empty string).通过使用负前瞻,您将能够处理大多数基本情况
By using negative look-ahead you will be able to handle most of the basic cases
您的第一个示例没有意义,但对于第二个示例,您可以使用类字符否定:
You first example makes no sense, but for the second you could use class character negation:
我试图理解正则表达式的逆的定义。
逆运算如何进行?应该是这样的吗
如果是这样,第一组结果和第二组结果之间有什么关系?如果不是,那是什么?
I am trying to understand the definition of inverse of a regex.
How would the inverse work? Should it be something like
If so, what is the relationship between the first set of results and the second? If not, then what is it?