【问题标题】:Using regex to match on pairs使用正则表达式匹配对
【发布时间】:2013-11-18 00:51:52
【问题描述】:

我想写一个正则表达式来匹配以下内容:

C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 
C1 to C2 , C2 to C3 , C3 to C4
C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C4 to C5 , C5 to C6 , C6 to C7

但是

我想以一种优雅的方式做到这一点,而不仅仅是完全匹配文本 - c1[ ](to|through)[ ]c2[ ][,][ ]c2[ ](to|through)[ ]c3 等。

这是一个词法分析器,它是用 lexx/yacc 正则表达式编写的。扫描仪是 Flex++。我想以 1 为增量匹配对,但不少于 4 且不超过 7。

为了记录,我已经广泛搜索了其他帖子,甚至询问了一些人。到目前为止没有任何想法。

【问题讨论】:

  • 请原谅我的迟钝,但你能不能更好地表述它,也许有一个输入和预期结果的例子。你的意思是匹配Cn ... C(n+1)
  • 您好。输入正是您在上面看到的。文本是上面的任何短语/行 - c1 到 c2 , c2 到 c3 等。所以是的,我的意思是 c(n+1)。当我说不少于四个时,我的意思是我想要不少于 4 个字母 C 和一个数字的组合,如 C1、C2、C3 和 C4。抱歉,不清楚!我是新手。
  • (1) 您使用的是 Perl 还是 Perl 兼容正则表达式 (PCRE)?第一个案例有一个带有嵌入式代码的优雅解决方案。 (2) 你确定这个功能应该在 lexer 中吗?通常,词法分析器只找到简单的标记(最好在线性时间),然后解析器将其组合到 AST。一旦一个部分被完全解析,就会进行语义验证。例如。对于分词器,C 代码( foo--bar } 可能看起来不错,但解析器会出错。同样,解析器可能会接受int foo = bar + 2,但语义验证会抱怨bar 未声明。
  • 好吧,这不是 Perl 或 PCRE。它是 Lex/YACC 正则表达式。对困惑感到抱歉。听起来我想做的事情不能用正则表达式来完成。

标签: regex perl matching flex-lexer


【解决方案1】:

上的数值必须自行检查,取决于上下文的“语义”正确性。

^c\d+[ ](to|through)[ ]c\d+[ ]([,][ ]c\d+[ ](to|through)[ ]c\d+)*$

这需要额外的处理。

原则上你可以合作

^c\d+[ ](to|through)[ ]((c\d+),\3 ...)*c\d+$
        1          1   23    3  ^    2

这将说明:第三组(此处)(c\d+) 必须在逗号 \3 之后重复。

【讨论】:

  • 好的,我会接受这个,看看我能做什么。感谢您的意见!
【解决方案2】:
 my $pairRE = qr/          # Start regular expression
                 \s*       # zero or more spaces
                 C         # 'C'
                 \d+       # one or more digits
                 \s+       # one or more spaces
                 (         # Start group
                   to        # 'to'
                   |         # or
                   through   # 'through'
                 )         # End group
                 \s+       # one or more spaces
                 C         # 'C'
                 \d+       # one or more digits
                 \s*       # zero or more spaces
                /x;        # End regular expression, eXtended syntax

  while (<DATA>) {
      print
        if /               # Start regular expression
            ^              # Start of line
            $pairRE        # a pair
            (              # Start group
             ,               # ','
             $pairRE         # a pair
            ){3,6}         # End group - match 3 to 6 copies of this group
           /x              # End regular expression, eXtended syntax
  }

__DATA__
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 
C1 to C2 , C2 to C3 , C3 to C4
C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C4 to C5 , C5 to C6 , C6 to C7

打印

C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6
C1 to C2 , C2 to C3 , C3 to C4 , C4 to C5
C2 to C3 , C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7
C3 to C4 , C4 to C5 , C5 to C6 , C6 to C7

【讨论】:

  • 这看起来很有趣。不确定我是否可以实现它,但我会看到。谢谢!
【解决方案3】:

如果您真的在使用 lex/yacc(或 flex/bison),则必须将两者结合使用。请原谅我生疏的语法。

弹性:

"C"[0-9]+  { yylval->num = atoi(yytext+1); return TOKEN_CNUM; }   
"to"       { return TOKEN_TO;      }
"through"  { return TOKEN_TO;      }
","        { return TOKEN_COMMA;   }   
[\n\r]     { return TOKEN_NEWLINE; }

野牛:

line: pair "," pair "," pair "," pair              {assert($1+1 == $3); assert($3+1 == $5); assert($5+1 == $7); }
    | pair "," pair "," pair "," pair "," pair     { /* similar */ }
    | /* for 6 pairs */
    | /* for 7 pairs */
    ;   

pair: TOKEN_CNUM TOKEN_TO TOKEN_CNUM { assert($1+1 == $3); $$ = $3; }                                                 
    ;   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 2010-12-14
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多