正则表达式在Javascript中无法正常工作?

时间:2014-03-21 11:58:13

标签: javascript php regex

In an earlier thread关于在类似国际象棋的字符串中的“注释”周围插入括号,我得到了很好的帮助,完成了一个与移动列表和注释分别匹配的正则表达式。

这是当前的正则表达式:

((?:\s?[\(\)]?\s?[\(\)]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2}(?:\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2})?\s?[()]?\s?[()]?\s?)+)|((?:(?!\s?[\(\)]?\s?[\(\)]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2}).)+)

三个捕获组是:

  1. e4 e5 2. f4 exf4 3.Nf3 ”等 - 即行动清单
  2. Blah blah blah blah ” - 即“评论”
  3. 评论“)(”评论 - 即关闭并开始调整,当一个国际象棋变体与结尾处的评论“完成”,另一个国际象棋变体与开头的评论“开始“
  4. 在此处采取行动:http://regex101.com/r/dQ9lY5

    一切正常用于“你的正则表达式” PCRE(PHP):它正确匹配所有三个组。当我切换到“你的正则表达式” Javascript 时,它会将所有内容与Capture Group 1匹配。我的正则表达式中是否存在Javascript正则表达式引擎不支持的内容?我试图研究这个,但一直无法解决它。关于这个主题有很多信息,我已经花了好几个小时。

    我知道一个解决方案是按原样使用正则表达式,并通过AJAX等将其传递给PHP,但我不知道该怎么做(它在我的列表中学习)。

    问题1:但我也非常好奇这个正则表达式在Javascript正则表达式引擎上不起作用。

    此外,这是我的Javascript CleanPgnText功能。我对while最感兴趣,但如果其他任何事情看似错误,我将不胜感激。

    function CleanPgnText(pgn) {
      var pgnTextEdited = '';
      var str;
      var pgnInputTextArea = document.getElementById("pgnTextArea");
      var pgnOutputArea = document.getElementById("pgnOutputText");
      str = pgnInputTextArea.value;
      str = str.replace(/\[/g,"(");     //sometimes he uses [ incorrectly for variations
      str = str.replace(/\]/g,")"); 
      str = str.replace(/[\n¬]*/g,"");  // remove newlines and that weird character that MS Word sticks in
      str = str.replace(/\s{2,}/g," "); // turn more than one space into one space
    
      while ( str =~ /((?:\s?[\(\)]?\s?[\(\)]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2}(?:\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2})?\s?[()]?\s?[()]?\s?)+)|((?:(?!\s?[\(\)]?\s?[\(\)]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2})[^\)\(])+)|((?:\)\s\())/g ) {
        if ($1.length > 0) {  //
          pgnTextEdited += $1;
        }
        else if ($2.length > 0) {
          pgnTextEdited += '{' + $2 + '}';
        }
        else if ($3.length > 0) {
          pgnTextEdited += $3;
        }
      }
    
      pgnOutputArea.innerHTML = pgnTextEdited;
    }
    

    问题2:关于=~声明中的while

    while ( str =~
    

    我从original thread中的有用代码中获取了=~,但它是用Perl编写的。我不太明白=~运算符的工作原理。我可以在Javascript中使用相同的运算符,还是应该使用其他东西?

    问题3:我可以像往常一样使用.length吗

    if ($1.length > 0) 
    

    查看第一个捕获组是否匹配?

    提前感谢您的帮助。 (如果regex101链接不适合你,你可以从原始线程获得一个样本pgn来测试。)

2 个答案:

答案 0 :(得分:1)

我更正了您的javascript代码并获得了以下内容:

http://jsfiddle.net/ZXG2H/

  1. 我个人认为匹配(组)问题与http://regex101.com/有关。你的表达在JavaScript(参见小提琴)和Java(具有转义修正)中绝对有效。我稍微简化了你的JavaScript并使用了参数而不是文本输入的pgn数据。

  2. 我不知道=~在JavaScript中可用,但也许我错了。使用JavaScript,您可以使用以下内容循环匹配:(为什么它的格式不像代码???)

    图案= / myregexp /; while((match = pattern.exec(mytext))!= null){     //做一点事 }

  3. 如果找不到匹配的组,则返回null。您可以使用上面的match变量来解析群组,而match[2]等索引与群组2匹配。

答案 1 :(得分:0)

我正在看你的新正则表达式,它不太正确。即使它看起来与@wumpz的JS代码一起使用,但是 您不能只在评论的部分中排除[^)(]个父母,因为您是 仅匹配字符串文字) (序列(在捕获组3中) 这可能会从匹配​​中排除父母,因为它不会成为新闻组的一部分 这是构建的。它不太可能因为这些动作与父母一致。

要解决这个问题,只需排除')(来自评论的`,然后先匹配它(组1) 另外,我留下了一些关于你的新正则表达式所做更改的注释 试试看。我认为@wumpz值得赞扬。

    #  /(\)\s*\()|((?:\s?[()]?\s?[()]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2}(?:\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2})?\s?[()]?\s?[()]?\s?)+)|((?:(?!\s?[()]?\s?[()]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-])(?!\)\s*\()[\S\s])+)/


    ( \) \s* \( )              # (1), 'Special Comment' configuration (must match first)
 |                           # OR,
    (                          # (2 start), 'Moves' configuration
         (?:
              \s? 
              [()]? \s? [()]? 
              \s? 
              [0-9]{1,3} \.{1,3}
              \s 
              [NBRQK]? [a-h1-8]? x? [a-hO] [1-8-] [O-]{0,3} [!?+#=]{0,2} [NBRQ]? 
              [!?+#]{0,2} 
              (?:
                   \s 
                   [NBRQK]? [a-h1-8]? x? [a-hO] [1-8-] [O-]{0,3} [!?+#=]{0,2} [NBRQ]? [!?+#]{0,2} 
              )?
              \s? 
              [()]? \s? [()]? 
              \s? 
         )+
    )                          # (2 end)
 |                           # OR,  
    (                          # (3 start), 'Normal Comment' configuration
         (?:
              (?!                        # Not the 'Moves configuration'
                   \s? 
                   [()]? \s? [()]? 
                   \s? 
                   [0-9]{1,3} \.{1,3}
                   \s 
                   [NBRQK]? [a-h1-8]? x? [a-hO] [1-8-] 

                   # ---- 
                   # Next line is not needed
                   # because all its items are
                   # optional
                   # ---- 
                   ### [O-]{0,3} [!?+#=]{0,2} [NBRQ]? [!?+#]{0,2}  <-  not needed
              )
              ### [^)(]    <- replaced by   '[\S\s]'  below
              # ---- 
              # The above line is replaced by any char.
              # because it excludes all ()'s and is not appropriate

              (?! \) \s* \( )            # Also, Not the 'Sspecial comment' configuration

              [\S\s]                     # Consume any char
         )+
    )                          # (3 end)

修改@wumpz JS代码,使用修改后的正则表达式

看起来像这样
 function CleanPgnText(pgn) {
     var pgnTextEdited = '';
     var str;
     var pgnOutputArea = document.getElementById("pgnOutputText");
     str = pgn;
     str = str.replace(/\[/g, "("); //sometimes he uses [ incorrectly for variations
     str = str.replace(/\]/g, ")");
     str = str.replace(/[\n¬]*/g, ""); // remove newlines and that weird character that MS Word sticks in
     str = str.replace(/\s{2,}/g, " "); // turn more than one space into one space

     //Start regexp processing
     var pattern = /(\)\s*\()|((?:\s?[()]?\s?[()]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2}(?:\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-][O-]{0,3}[!?+#=]{0,2}[NBRQ]?[!?+#]{0,2})?\s?[()]?\s?[()]?\s?)+)|((?:(?!\s?[()]?\s?[()]?\s?[0-9]{1,3}\.{1,3}\s[NBRQK]?[a-h1-8]?x?[a-hO][1-8-])(?!\)\s*\()[\S\s])+)/g;

     while ((match = pattern.exec(str)) != null) {
         if (match[1] != null) {           // Special Comment configuration, don't add '{}'
             pgnTextEdited += match[1];
         } else if (match[2] != null) {    // Moves configuration  
             pgnTextEdited += match[2];
         } else if (match[3] != null) {    // Normal Comment configuration, add '{}'
             pgnTextEdited += '{' + match[3] + '}';
         }
     }
     //end regexp processing

     pgnOutputArea.innerHTML = pgnTextEdited;
 }

在Perl程序中运行它,输出为:

{哈巴罗夫斯克是俄罗斯远东的首都。我16岁的对手是一个有前途的本地神童。现在他是一个非常强大的FM,FIDE等级为2437,并且在美国生活......一个小世界。} 1. e4 c5 2. Nf3 e6 3. c3 Nf6 4. e5 Nd5 5. d4 cxd4 6. cxd4 d6 7. Nc3 Nc6 8. Bd3!? Nxc3 9. bxc3 dxe5 10. dxe5 Qa5 11. O-O Be7 12. Qb3 Nxe5 13. Nxe5 Qxe5 14. Bb5 + Kf8 15. Ba3 Qc7 16. Rad1 g6 17. c4! Bxa3 18. Qxa3 + Kg7 19. Rd6 Rd8 20. c5 Bd7 21. Bc4 Bc6 22. Rfd1 Rd7 23. Qg3 Rad8 {最后有准确,稳定的游戏黑色已经巩固但白色仍然保持一定的压力并且对棋子有一些补偿。} 24. h4 {在这样的位置上进行典型的游行,没有别的办法可以做得更好。} 24 ... h5 ?! (24 ... h6 {将是一个更谨慎的回应。})({但最好的防御是} 24 ... Rd6!25。cd6 Qa5)25。Qe5 + Kh7 26. Bd3 {非常自然} 26 ... KH6? ({Missing} 26 ... Ba4!27. Qxh5 + Kg7 28. Qe5 + Kg8!{现在Black有很多自己的威胁。怀特将不得不强迫永久性的...... 29. h5!Bxd1 30. h6 f6 31. Qxf6 Bh5 32. Qxe6 + Kh7 33. Bxg6 + Bxg6 34. Qxg6 + Kh8 35. Qf6 + {现在,在26 ...... Kh6之后,一切都准备好迎接决定性的打击。})27。Qf6! Kh7({没有} 27 ... Rxd6 28. cxd6 Rxd6?{由于} 29. Qh8#)28。g4! hxg4 29. h5 Rxd6 30. cxd6 Rxd6 31. hxg6 + Kg8 32. g7! {此典当是至关重要的因素,直到现在结束。随着任何其他举动,怀特失败。} 32 ... Qd8! {对Qh6和Qh8唯一的防御检查或控制。} 33. Qh6 f5 34. Rd2 !! {想法是白车不能带一张支票了。主教将很容易解决破碎的Bxf5或Bc4。 d档上的黑色针是一种幻觉!事实上,它是黑色的车被固定,不能留下d档。} 34 ... Bd5({最好的尝试 - 关闭d文件,保护更多的e6兵。没有帮助} 34 ... Rd7 35. Bf5 ef5 36 Qh8 Kf7 37. Rd7)({但也许最好的实际机会是} 34 ... g3!?{和现在} 35. Bxf5 {因为没有赢得} 35 ... gxf2 + 36. Kh2 f1 = N + !37. Kh3 Bg2 +!38. Rxg2 Rd3 +!39。Bxd3 Qxd3 + {有惊人的永恒} 40. Kh4 Qe4 + 41. Rg4 Qh1 + 42. Kg5 Qd5 + 43. Kf6 Qd8 + 44. Kg6 Qd3 +)({但之后} 34 .. .g3!?{White使用另一种侧翼战术:} 35. Bc4!Bd5 36. Bxd5 exd5 37. Qh8 + Kf7 38. Rc2 gxf2 + 39. Kf1!{并且没有防御Rc8。现在在35 ... Bd5之后再一切看起来都很受保护。})35。Qh8 Kf7 36. Bb5! {主教仍在努力突破。即将到来的Be8是杀手。} 36 ...... Qg8 37. Be8 +! Qxe8 38. Qe8 + Kxe8 39. g8 = Q + Kd7 40. Qg7 + {这是怀特的第40次移动这意味着时间控制已经结束了。我的时间很短。一个女王的棋子和三个棋子是不够的。布莱克辞职了。 1-0 }