17

我正在开发自己的 JavaScript 库以支持正则表达式的新元字符和功能,我想找到一个[^xy]不等同于(?!x).(或更具体地说(?:(?!x|y).))的情况。

以示例文本为例:"abc\n"

假设我想模拟 Perl 正则表达式:/\A.{3}\Z/s

使用单行标志,JavaScript 正则表达式应该等价于:/^[\s\S]{3}\n*$(?!\s)/( \Abecome ^, .become [\s\S], \Zbecome \n*$(?!\s))

现在,/^.{3}$/会失败,但/^[\s\S]{3}\n*$(?!\s)/会捕获“abcabc”(与 Perl 正则表达式相同)

由于\Z包含的不仅仅是元字符,因此模拟[^\Z]似乎更加困难。

以示例文本为例:"abcabc\n"

为 Perl 正则表达式提议的 JavaScript 正则表达式/.{3}[^\Za]/g将是.{3}(?:(?!\n*$(?!\s)|a).)/g

两者都会匹配"bcab"

所以,最后,我再次提出这个问题。是否存在[^xy]不等同于(?:(?!x|y).)这种情况的情况,也许在更复杂的正则表达式中,前瞻会改变情况?

4

5 回答 5

9

对于输入字符串"x\na",2 个正则表达式给出不同的输出,因为.不匹配换行符。

console.log("x\na".match(/(?:(?!x|y).)/))
["a", index: 2, input: "x↵a"]
console.log("x\na".match(/[^xy]/))
["↵", index: 1, input: "x↵a"]

如果更改.[\s\S],则在这种情况下输出是相同的:

console.log("x\na".match(/(?:(?!x|y)[\s\S])/))
["↵", index: 1, input: "x↵a"]

我现在想不出任何其他情况。

于 2013-06-27T20:38:36.867 回答
5

[^xy]没有不等于的情况(?!x|y).

只有您已经描述过的一个:JS 点与换行符不匹配,需要替换为[\s\S].

\Z变成\n$(?!\s)

那看起来不对。在字符串 ( \z/ $) 的结尾之后,无论是否有空格,都不会有任何内容。Afaik,\Z是一个零宽度断言(它不消耗换行符)并且应该等同于

(?=\n*$)
//   ^ not sure whether ? or *

由于\Z包含的不仅仅是元字符,因此模拟[^\Z]似乎更加困难。

“元字符”是什么意思?这是一个零宽度断言,在字符类中没有多大意义。我猜这要么是语法错误,要么会被逐字解释(未转义)为[^Z].

于 2013-06-27T20:59:39.897 回答
4

[^xy]将匹配\n(?!x|y).默认不匹配\n(因为.不匹配\n

我不相信 javascript 有一个“dotall”或“single-line”修饰符,但是每个浏览器的新版本每隔几个月就会出现一次,我已经迷失了方向。

于 2013-06-27T20:33:41.610 回答
0

正如其他人所说,您应该在替换中使用[\s\S]而不是。.否则,如果您只是通过文字字符串进行转换,则需要处理更多的事情。特别是元字符和转义序列:

[^*)] => (?!\*|\))[\s\S]

但我想无论如何你都需要特别注意解析和编写元字符。

最棘手的可能\b是,因为它是字符类中的一个字符(退格)和外部的单词边界。因此,在替换中,您必须使用八进制或十六进制转义:

[^a\b] => (?!a|\10)[\s\S] 
    or => (?!a|\x08)[\s\S]

除此之外,两者应该始终是等价的。

于 2013-06-27T21:17:16.500 回答
0

格式与 x 是零宽度断言而不是实际字符的情况[^xy]不同(?:(?!x|y).)的情况,例如:

鉴于此示例文本:ab-yz

正则表达式:[^\by] 示例:http ://www.rubular.com/r/ERKrqyeAs9

回报:

[0] => a
[1] => b
[2] => -
[3] => z

然而

正则表达式:(?:(?!\b|y).)示例:http ://www.rubular.com/r/V5RdyQEQo5

回报:

[0] => b
[1] => z

其他非等价表达式,这些主要集中在相同的语法在字符类内部或外部具有不同含义的事实:

  • [^^y]产生 a,b,-,z 不等于(?:(?!^|y).)产生 b,-,z
  • [^.y]产生 a,b,-,z 不等于(?:(?!.|y).)什么也不产生

或者你可以在 Perl 的 unicode nugget 中试试这个:http: //ideone.com/2xMfkQ

print "\ncapture\n";
@m = ("ss" =~ m/^(?:(?!\xDF|y).)+$/ui ); 
print for @m;

print "\nclass\n";
@m = ("ss" =~ m/^[^\xDFy]+$/ui) ; 
print for @m;

产量:

capture

class
1
于 2013-06-27T21:30:37.930 回答