修改参考编号组以匹配

时间:2011-11-23 17:25:26

标签: regex

我希望连续几年匹配YYYY-YY

我正在尝试匹配所有第二个YYYYYY中第3个和第4个字符的位置,其中添加了1个。

到目前为止,我已经{19|20}(\d{2})-(\d{2}),但不确定如何使用?参考(1),或者我是否正确地采用这种方法并找出不可避免的方法用这种方法“未知的未知数”(如YY99)?

修改

匹配:1999-002010-112011-122029-30
不匹配:2010-122010-092011-22011-2012

3 个答案:

答案 0 :(得分:2)

有两种方式:

  1. 困难的方法是使用backrefs。每个小数位需要有10个捕获缓冲区,将被检查。因此,在这种情况下,需要20个。在高级正则表达式引擎中可能有其他方法可以在引擎内执行递归和/或代码执行(eval)。

  2. 简单方法,只需抓取数字并进行后期处理。

  3. 我不确定您使用的是哪个引擎,所以下面是Perl中的一个示例,用作说明这两种方式的示例。

    @samples = qw( 1999-10 1999-00 2010-11 2011-12 2029-30 2010-12 2010-09 2011-2 2011-2012 );
    
    $regex_hard = qr{ 
      ^
       (?:19|20)
       (?:1()|2()|3()|4()|5()|6()|7()|8()|9()|0())
       (?:1()|2()|3()|4()|5()|6()|7()|8()|9()|0())
       -
       (?: \19(?:\1(?:2)|\2(?:3)|\3(?:4)|\4(?:5)|\5(?:6)|\6(?:7)|\7(?:8)|\8(?:9)|\9(?:0)|\10(?:1))
         | (?!\19)\d
       )
       (?:\11(?:2)|\12(?:3)|\13(?:4)|\14(?:5)|\15(?:6)|\16(?:7)|\17(?:8)|\18(?:9)|\19(?:0)|\20(?:1))
      $
    }x;
    
    for $date (@samples) {
       print "$date";
       if ($date =~ /$regex_hard/) {
           print "  ~  matched $&";
       }
       print "\n";
    }
    
    print "\n----------\n";
    
    
    $regex_easy = qr{ ^ (?:19|20) (\d\d) - (\d\d) $ }x;
    
    print "\n";
    for $date (@samples) {
       print "$date";
       if ($date =~ /$regex_easy/ && $2 == ($1 == 99 ? 0 : $1+1) ) {
           print "  ~  matched $&";
       }
    }
    

    输出:

    1999-10
    1999-00  ~  matched 1999-00
    2010-11  ~  matched 2010-11
    2011-12  ~  matched 2011-12
    2029-30  ~  matched 2029-30
    2010-12
    2010-09
    2011-2
    2011-2012
    
    ----------
    1999-10
    1999-00  ~  matched 1999-00
    2010-11  ~  matched 2010-11
    2011-12  ~  matched 2011-12
    2029-30  ~  matched 2029-30
    2010-12
    2010-09
    2011-2
    2011-2012
    

答案 1 :(得分:1)

如果你问我认为你在问什么:

  

如果两位数年份需要在四位数年份后的一年内,我如何以YYYY-YY格式匹配一系列年份?例如,我想匹配1991-922010-11但不匹配1990-98,绝对不匹配2009-03

然后我认为这不可能与正则表达式(当然不是任何流行或知道的语言或工具)。你最接近它的是使用这样的东西:

(19|20)(\d\d)-(\d\d)

...然后手动或使用代码验证第二个和第三个捕获组在存储,替换或以其他方式处理匹配之前仅具有值1的差异。

修改 在参考你的评论时,我不确定做一个蛮力(1972-73|1973-74|1974-75...)或在潜在的匹配后进行检查以验证数字关系是否更快 - 看起来效率都不高,但似乎有点似乎更好(更灵活)和更令人满意:验证匹配后的算法。效率的答案可能在于你想要支持多少年。

在我做到这一点之前,我需要一点时间来做几件不相关的事情,但是你可以回来看看,其他人可能比我有更多的时间,或者我很快就能做到。 (现在真的更像是code golf type of thing - 你可以尝试一下)

答案 2 :(得分:0)

如果您可以使用AWK,那么可以这样做 -

假设您有一个年份由,分隔的文件。

[jaypal~/Temp]$ cat years
1999-00,2010-11,2011-12,2029-30,2010-12,2010-09,2011-2,2011-2012

使用SED,您可以将文件设为 -

[jaypal~/Temp]$ sed 's/,/\n/g' years
1999-00
2010-11
2011-12
2029-30
2010-12
2010-09
2011-2
2011-2012

此输出可以通过管道输入AWK以查找连续的年份 -

[jaypal~/Temp]$ sed 's/,/\n/g' years | 
awk -F"-" '{a=substr($1,3,2); a=a+1; if (a==$2) print; else if (length(a)>2 && substr(a,2,2)==$2) print}'
1999-00
2010-11
2011-12
2029-30