【问题标题】:Regex skip in C++C++ 中的正则表达式跳过
【发布时间】:2016-06-07 03:15:54
【问题描述】:

这是我的字符串:

/*
  Block1 {

    anythinghere
  }
*/

// Block2 { }
# Block3 { }

Block4 {

    anything here
}

我正在使用这个正则表达式来获取每个块的名称和内部内容。

regex e(R"~((\w+)\s+\{([^}]+)\})~", std::regex::optimize);

但是这个正则表达式也包含在描述中。 PHP 中有一个“跳过”选项,您可以使用它来跳过所有描述。

What_I_want_to_avoid(*SKIP)(*FAIL)|What_I_want_to_match

但这是 C++,我不能使用这种跳过方法。我应该怎么做才能跳过所有描述并在 C++ 正则表达式中获取 Block4?

这个正则表达式检测到Block1Block2Block3Block4,但我想跳过Block1Block2Block3,只得到Block4(跳过描述)。我如何必须编辑我的正则表达式才能获得 Block4(描述之外的所有内容)?

【问题讨论】:

  • 看起来您尝试使用正则表达式完成一些应该由解析器完成的事情。话虽如此,从您的问题中根本不清楚您真正想要匹配什么。
  • “跳过所有描述”是什么意思?你是不是想不匹配 cmets?
  • yes 尽量不匹配 cmets
  • 您可以跳过 cmets,但请注意 ; Block3 { hi } 如果在第一条评论之前不存在任何内容,则 C++ 无效。
  • 你可以解析块,但是{ ...}之间的部分可以在{ ..."}";....}之类的字符串中巧妙地屏蔽。您必须这样做的方式是将 cmets 或字符串或您的块匹配为单个表达式,即 comments|strings|(block{(?:comments|strings|.)*}) 然后查找要匹配的捕获组 1。我可以给你正则表达式,但它很大。

标签: c++ regex c++11


【解决方案1】:

Tl;DR:Regular expressions cannot be used to parse full blown computer languages。你想做的事情不能用正则表达式来完成。您需要开发一个 mini-C++ 解析器来过滤掉 cmets。 The answer to this related question might point you in the right direction.

正则表达式可用于处理regular expressions,但C++、PHP、Java、C#、HTML 等计算机语言的语法更为复杂,其中包含一个名为“中间递归”的属性。中间递归包括复杂性,例如任意数量的匹配括号、开始/结束引号和可以包含符号的 cmets

如果您想更详细地了解这一点,read the answers to this question about the difference between regular expressions and context free grammars。如果您真的很好奇,请报名参加Formal Language Theory 课程。

【讨论】:

    【解决方案2】:

    既然您请求了这么长的正则表达式,就在这里。

    这不会处理 嵌套block{ block{ } } 这样的块
    它只会匹配block{ block{ } }。

    由于您指定使用 C++11 作为引擎,所以我没有使用
    递归。如果您要使用,这很容易更改为使用递归
    PCRE 或 Perl,甚至 BOOST::Regex。如果你想看,请告诉我。

    因为它有缺陷,但适用于您的示例。
    它不会做的另一件事是解析 Preprocessor Directives '#...' 因为
    我忘记了规则(以为我最近做了,但找不到记录)。

    要使用它,请坐在while ( regex_search() ) 循环中寻找匹配项
    捕获组 1、if (m[1].success) 等。这将是您的障碍。
    其余匹配项针对 cme​​ts、引号或非 cmets、无关
    到块。这些必须匹配以推进匹配位置。

    代码是 long 并且是多余的,因为在 C++11 EMCAscript 中没有函数调用(递归)。就像我说的,使用 boost::regex 什么的。

    基准测试

    示例:

    /*
      Block1 {
    
        anythinghere
      }
    */
    
    // Block2 { }
    
    Block4 {
    
       // CommentedBlock{ asdfasdf }
        anyth"}"ing here
    }
    
    Block5 {
    
       /* CommentedBlock{ asdfasdf }
        anyth}"ing here
       */
    }
    

    结果:

    Regex1:   (?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(\w+\s*\{(?:(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?!\})[\S\s][^}/"'\\]*))*\})|[\S\s](?:(?!\w+\s*\{(?:(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?!\})[\S\s][^}/"'\\]*))*\})[^/"'\\])*)
    Options:  < none >
    Completed iterations:   50  /  50     ( x 1000 )
    Matches found per iteration:   8
    Elapsed Time:    1.95 s,   1947.26 ms,   1947261 µs
    

    正则表达式解释:

        # Raw:        (?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(\w+\s*\{(?:(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?!\})[\S\s][^}/"'\\]*))*\})|[\S\s](?:(?!\w+\s*\{(?:(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|//(?:[^\\]|\\\n?)*?\n)|(?:"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|(?!\})[\S\s][^}/"'\\]*))*\})[^/"'\\])*)
        # Stringed:  "(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/|//(?:[^\\\\]|\\\\\\n?)*?\\n)|(?:\"[^\"\\\\]*(?:\\\\[\\S\\s][^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\[\\S\\s][^'\\\\]*)*'|(\\w+\\s*\\{(?:(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/|//(?:[^\\\\]|\\\\\\n?)*?\\n)|(?:\"[^\"\\\\]*(?:\\\\[\\S\\s][^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\[\\S\\s][^'\\\\]*)*'|(?!\\})[\\S\\s][^}/\"'\\\\]*))*\\})|[\\S\\s](?:(?!\\w+\\s*\\{(?:(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/|//(?:[^\\\\]|\\\\\\n?)*?\\n)|(?:\"[^\"\\\\]*(?:\\\\[\\S\\s][^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\[\\S\\s][^'\\\\]*)*'|(?!\\})[\\S\\s][^}/\"'\\\\]*))*\\})[^/\"'\\\\])*)"     
    
    
        (?:                              # Comments 
             /\*                              # Start /* .. */ comment
             [^*]* \*+
             (?: [^/*] [^*]* \*+ )*
             /                                # End /* .. */ comment
          |  
             //                               # Start // comment
             (?: [^\\] | \\ \n? )*?           # Possible line-continuation
             \n                               # End // comment
        )
     |                                 # OR,
    
        (?:                              # Non - comments 
             "
             [^"\\]*                          # Double quoted text
             (?: \\ [\S\s] [^"\\]* )*
             "
          |  '
             [^'\\]*                          # Single quoted text
             (?: \\ [\S\s] [^'\\]* )*
             ' 
          |  
             (                                # (1 start), BLOCK
                  \w+ \s* \{               
                  ####################
                  (?:                              # ------------------------
                       (?:                              # Comments  inside a block
                            /\*                             
                            [^*]* \*+
                            (?: [^/*] [^*]* \*+ )*
                            /                                
                         |  
                            //                               
                            (?: [^\\] | \\ \n? )*?
                            \n                               
                       )
                    |  
                       (?:                              # Non - comments inside a block
                            "
                            [^"\\]*                          
                            (?: \\ [\S\s] [^"\\]* )*
                            "
                         |  '
                            [^'\\]*                          
                            (?: \\ [\S\s] [^'\\]* )*
                            ' 
                         |  
                            (?! \} )
                            [\S\s]                          
                            [^}/"'\\]*                      
                       )
                  )*                               # ------------------------
                  #####################          
                  \}                               
             )                                # (1 end), BLOCK
    
          |                                 # OR,
    
             [\S\s]                           # Any other char
             (?:                              # -------------------------
                  (?!                              # ASSERT: Here, cannot be a BLOCK{ }
                       \w+ \s* \{                      
                       (?:                              # ==============================
                            (?:                              # Comments inside a block
                                 /\*                              
                                 [^*]* \*+
                                 (?: [^/*] [^*]* \*+ )*
                                 /                                
                              |  
                                 //                               
                                 (?: [^\\] | \\ \n? )*?
                                 \n                               
                            )
                         |  
                            (?:                              # Non - comments inside a block
                                 "
                                 [^"\\]*                          
                                 (?: \\ [\S\s] [^"\\]* )*
                                 "
                              |  
                                 '
                                 [^'\\]*                          
                                 (?: \\ [\S\s] [^'\\]* )*
                                 ' 
                              |  
                                 (?! \} )
                                 [\S\s]                          
                                 [^}/"'\\]*                       
                            )
                       )*                               # ==============================
                       \}                               
                  )                                # ASSERT End
    
                  [^/"'\\]                         # Char which doesn't start a comment, string, escape,
                                                   # or line continuation (escape + newline)
             )*                               # -------------------------
        )                                # Done Non - comments 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多