如何在没有复杂的手工编辑的情况下将任何正则表达式转换为自身的补充?

blu*_*ers 14 regex regex-negation

以下是伪示例,不是真正的正则表达式,但仍然是我的意思的一个例子:


.* (anything)

-.* (NOT anything)
Run Code Online (Sandbox Code Playgroud)
[A-Z] (Any letter A to Z, caps only)

-[A-Z] (NOT any letter A to Z, caps only)
Run Code Online (Sandbox Code Playgroud)

编辑:在问题中将逆转换为补语.以下是改变的地方:"将任何正则表达式转化为自身的补充 "

Eam*_*nne 13

首先,我相信你的意思是正则表达式的补充,而不是它的反面.正则表达式的倒数没有多大意义; 但是如果把它视为一个函数,我想你可以说匹配器的逆是生成所有匹配字符串的生成器 - 或者其他东西.另一方面,语言的补充是所有那些不是原始语言的字符串.

然后,这里有两个视图需要考虑:

从根本上

常规语言的补充是常规的.这意味着可以为补码生成一个接受的DFA(这样做非常简单,实际上:只需将非接受状态集与接受状态集交换).任何这样的DFA都可以表示为正则表达式 - 所以原则上你确实可以制作这样的正则表达式.

请参阅维基百科关于常规语言的文章作为起点.

几乎

现今大多数现代语言中使用的典型perl兼容正则表达式语法没有互补运算符.对于完整的正则表达式,您可以通过使用负向前瞻操作符来获得类似的东西:(?!X)当X不能时,将精确匹配字符串.但是,对于补充运算符来说,这是一个很差的替代品,因为你无法以通常的方式将它用作更大的正则表达式的一部分; 这个正则表达式不"消耗"输入,这意味着它与其他运算符一起表现不同.

例如,如果您将数字字符串匹配[0-9]*为匹配您要^添加和追加的整个字符串$,但要使用此技术来查找您需要编写的补充^(?!^[0-9]*$).*$- 并且这种否定正则表达式的常用连接是,据我所知,可以撤销.

具有讽刺意味的是,由于反向引用,正则表达式的实际化身在理论上更强大,但实际上不太灵活,因为语言不能很容易地完全表达补语和交集操作.


Eya*_*yal 8

只需运行正则表达式并逻辑反转输出.所以改变:

if(/foo/)
Run Code Online (Sandbox Code Playgroud)

至:

if(!/foo/)
Run Code Online (Sandbox Code Playgroud)

字符类可以用前导克拉反转:

[AZ] - > [^ AZ]

如果你将说明符大写,那么许多特殊字符也会反转.

\s whitespace
\S non-whitespace
\w word character
\W non-word-character
\d digit
\D non-digit
Run Code Online (Sandbox Code Playgroud)

  • "需要"什么?家庭作业?目前还不清楚逆转是什么. (2认同)

Tim*_*ker 6

需要考虑的几种变化:

匹配由一组特定字符组成的字符串: ^[a-z]*$

匹配包含除特定字符集之外的任何字符串的字符串:^[^a-z]*$

请注意,有一些快捷方式:

  • \w:任何字母数字字符(包括_),
  • \W:任何非字母数字字符;
  • \s:任何空白字符,
  • \S:任何非空白字符,
  • \d:任何数字,
  • \D:任何非数字.

这可能会变得非常复杂,例如,如果你想......

  • 只有非字母:[\d_\W]或
  • 只有字母:( [^\d_\W]即"不是数字,不是a _,而不是非字母数字字符")

匹配包含子字符串的字符串: ^.*substring.*$

匹配不包含子字符串的字符串:^(?:(?!substring).)*$

注意我们如何检查字符串中的每个位置是否存在子串的"不存在".您还可以替换任何正则表达式substring来匹配包含或不包含某个子正则表达式的字符串.


匹配任何东西:( .*如果你想匹配换行符,你必须设置编程语言的相应选项,例如re.DOTALL在Python中)

如果您不知道如何设置该选项,请匹配任何内容: [\s\S]*

绝不匹配(无论出于何种原因):

  • $^ (即在字符串开头之前匹配字符串的结尾),
  • \b\B (匹配同时存在单词边界而不是单词边界的位置)或
  • (?!) (匹配一个无法匹配空字符串的位置).