代码之家  ›  专栏  ›  技术社区  ›  SamGoody

regex在ie中返回值,在firefox和safari/chrome中返回“undefined”

  •  0
  • SamGoody  · 技术社区  · 15 年前

    有正则表达式:

    .*?
    (rule1|rule2)
    (?:(rule1|rule2)|[^}])*
    

    (它被设计用来解析CSS文件,而“规则”是由JS生成的。)

    当我在IE中尝试这个的时候,一切都会正常工作。 当我在雷吉克斯巴迪或雷吉克斯教练那里尝试的时候也是一样。

    但是当我在Firefox或Chrome中尝试时,结果会丢失值。
    有人能解释一下真正的浏览器在想什么,或者我怎样才能获得与IE类似的结果吗?

    若要查看实际情况,请加载一个提供交互式测试的页面,例如W3Schools试用编辑器。

    以下是可以粘贴的源: http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_regexp_exec

    <html>
    <body>
    
    <script type="text/javascript">
    
    var str="#rot { rule1; rule2; }";
    
    var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/i;
    
    var result=patt.exec(str);
    for(var i = 0; i < 3; i++) document.write(i+": " + result[i]+"<br>"); 
    
    </script>
    </body>
    </html>
    

    以下是IE中的输出:

    0: #rot { rule1; rule2; 
    1: rule1
    2: rule2
    

    下面是firefox和chrome中的输出:

    0: #rot { rule1; rule2; 
    1: rule1
    2: undefined
    

    当我使用string.match尝试相同的方法时,我会在所有浏览器中返回一个未定义的数组,包括ie。

    var str="#rot { rule2; rule1; rule2; }";
    var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/gi;
    var result=str.match(patt);
    for(var i = 0; i < 5; i++) document.write(i+": "+result[i]+"<br>"); 
    

    据我所知,这个问题是最后一个没有捕获括号的问题。
    当我删除它们时,结果是一致的跨浏览器的,match()得到结果。

    然而,它 在所有浏览器中,从最后一个圆括号捕获以下示例:

    <script>
    var str="#rot { rule1; rule2 }";
    var patt=/.*?(rule1|rule2)(?:(rule1 |rule2 )|[^}])*/gi;
    var result=patt.exec(str);
    for(var i =0; i < 3; i++) document.write(i+": "+result[i]+"<br>"); 
    </script>
    

    注意,我在第二个regex中为模式添加了一个空格。
    如果在第二个regex中的字符串中添加任何负号字符,则同样适用:

    var patt=/.*?(rule1|rule2)(?:(rule1[^1]|rule2[^1])|[^}])*/gi;
    

    咒骂是怎么回事?!
    我尝试过的所有其他字符串都会导致第一组非捕获。 非常感谢您的帮助!

    编辑: 根据马修的建议,这段代码被缩短了,并且进行了许多小时的研究。
    标题已更改,以便更容易找到线程。

    我把马修的答案标为正确的,因为它经过了很好的研究和描述。
    我下面的回答(在马修修改他的之前写的)用更简单、更直接的术语阐述了逻辑。

    5 回复  |  直到 8 年前
        1
  •  1
  •   Matthew Flaschen    15 年前

    IE是错的。在ecmascript中,只有一个选项可以生成字符串。其他人都必须 undefined (不是) "" 或者别的什么)。

    所以对于你的选择,包括 (transform[^-][^;}]+)|(transform-origin[^;}]+) ,firefox和chrome将失败的捕获设置为 未定义 .

    ECMAScript 5标准(_§15.10.2.3)中有一个具体的例子:

    注意正则表达式运算符 将两个备选方案分开。这个 图案首先尝试与左侧匹配 备选方案(后面是 正则表达式);如果失败, 它试图匹配右边 分离(随后是 正则表达式)。如果左边 另一种选择,右分离, 续集都有选择点, 续集中的所有选择都会被尝试 在进入下一个选择之前 左边的选项。如果选择 左边的选项已经用尽了, 而是尝试正确的分离 左边的选项。任何捕捉 括号位于 模式被跳过,产生未定义的

    rule1 rule2 ; [^;}] [^}]

    *

    (transform-origin[^;}]+))

    match

    var str="#rot { rule1; rule2; }";
    var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/i;
    
    .*? - "#rot { "
    
    (rule1|rule2) - "rule1"
    match[1] = "rule1"
    

    [^}] - ";"
    match[2] = undefined 
    

    [^}] - " "
    match[2] = undefined 
    

    (rule1|rule2) - "rule2"
    match[2] = "rule2"
    

    str.match String.match g

    var str="#rot { rule1; rule2 }";
    var patt=/.*?(rule1|rule2)(?:(rule1 |rule2 )|[^}])*/gi;
    
    .*? - "#rot { "
    (rule1|rule2) - "rule1"
    match[1] = "rule1"
    

    (rule1 |rule2 ) - "rule2 "
    match[2] = "rule2 "
    

        2
  •  4
  •   SamGoody    15 年前

    var str = 'abcdef';
    var pat = /([a-f])+/;
    


    var str = 'abcdefg';
    var pat = /(?:([a-f])|g)+/;
    




        3
  •  2
  •   chocolateboy Chris Marie    8 年前

    /^(?:(Foo)|Bar)(?:(Foo)|Bar)/.exec("FooBar") // => [ 'FooBar', 'Foo' ]
    /^(?:(Foo)|Bar){2}/.exec("FooBar")           // => [ 'FooBar', undefined ]
    

    (?:(Foo)|Bar) atom quantifier

    ECMAScript spec

    documented


    Perl-flavored

    "FooBar".match(/^(?:(Foo)|Bar)*/)[1] // => undefined
    
    ("FooBar" =~ m/^(?:(Foo)|Bar)*/)[0] # => "Foo"
    
    re.match("^(?:(Foo)|Bar)*", "FooBar").group(1) # => "Foo"
    
    "FooBar"[/^(?:(Foo)|Bar)*/, 1] # => "Foo"
    
        4
  •  0
  •   Ben Lee    15 年前

    (?:^|})
    ([^{]+)
    [^}]+?-moz-
    ((transform[^-][^;}]+)|(transform-origin[^;}]+))
    (-moz-(?:(transform[^-][^;}]+)|(transform-origin[^;}]+))|[^}])*
    
        5
  •  0
  •   Jason McCreary    15 年前

    (?:(transform[^-][^;}]+)|(transform-origin[^;}]+))
    (?:-moz-(?:(transform[^-][^;}]+)|(transform-origin[^;}]+))|[^}])*
    

    transform origin

    ((?:-moz-)?(?:transfrom-origin[^;}]+))