regex - 使用 Perl 验证年份范围

标签 regex perl

这些是我们源文件标题中的有效年份,在版权行中:

2016
2007,2016
2007-2010,2016
2010,2012-2016

当前年份(2016 年)应该是其中的一部分。

无效的:
2016,2007 # not in order
2010-2007,2016 #range not in order.
2010-2015 # current year missing.

我制作了如下脚本,仍在处理它,有没有更好的方法来检查它?
use strict;
use warnings;
use List::Util 'first';
use Time::Piece;

my $t = Time::Piece->new();
my $currentYear=$t->year;

my $filename="sample.txt"; # this file name will be passed-in to the script.
my $fileContent=`cat $filename`;
my $copyrightFound = first { /copyright .* Shakespeare/i } $fileContent;
if (!$copyrightFound) {
     print "\nERROR: Copyright missing\n";
     exit;
}
#copyright Found
print $fileContent;
if ($fileContent =~ /Copyright \(c\) (.*) by Bill Shakespeare\s+.*All rights reserved./) {
    print "\nCopyright is good: $1\n";
    my $years = $1;
    print "\n$years, $currentYear\n";
    #e.g: 2016
    if ($years !~ ', ' && $years !~ '-') {
       print "\nerror\n" if ($years !~ /$currentYear/);
    }
    #e.g: 2010-2016
    elsif ($years !~ ', ') {
       print "\nError\n" if ($years !~ /\-$currentYear$/);
    }
    #eg: 2010, 2016
    elsif ($years !~ '-') {
       print "\nError\n" if ($years !~ /\, $currentYear$/);
    }
    #e.g: 2008, 2010, 2011-2016
    elsif ($years =~ '-' && $years =~ ', ') {
       print "\nError 5\n" if ($years !~ /\d\d\d\d, \d\d\d\d\-$currentYear$/);
    }
    else {
       print "invalid format"
    }

} else {
      print "\nCopyright needs to be fixed\n";
}

sample.txt 有:
Copyright (c) 2008, 2010, 2011-2016 by Bill Shakespeare
All rights reserved.

最佳答案

您可以使用 Set::IntSpan验证日期:

use warnings;
use strict;
use Set::IntSpan qw();

my $currentYear = 2016;

while (<DATA>) {
    s/\s+//g;
    my $ok = 0;
    if (Set::IntSpan->valid($_)) { # Checks order
        my $set = Set::IntSpan->new($_);
        my @years = $set->elements();
        $ok = 1 if grep { $_ == $currentYear } @years;
    }
    print "$ok : $_\n";
}

__DATA__
2007
2007, 2016
2007-2010,2016
2010,2012-2016
2016,2007
2010-2007,2016
2010-2015

这打印:
0 : 2007
1 : 2007,2016
1 : 2007-2010,2016
1 : 2010,2012-2016
0 : 2016,2007
0 : 2010-2007,2016
0 : 2010-2015

简化使用 member而不是 grep ,正如 pilcrow 所推荐的在评论中:
my $ok = 0;
if (Set::IntSpan->valid($_)) { 
    my $set = Set::IntSpan->new($_);
    $ok = 1 if $set->member($currentYear);
}
print "$ok : $_\n";

关于regex - 使用 Perl 验证年份范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36987918/

相关文章:

Python 正则表达式 : is there a symbol to search for more than one occurence of a pattern?

java - 使用正则表达式从字符串中获取信封ID

mysql - 如何在 Perl 中干净地提取 MySQL 枚举值?

perl - 在 Perl 中实现 CLI 工具的最佳实践是什么?

perl - Web 上的官方 Perl 文档是什么?

multithreading - Perl TCP 服务器处理多个客户端连接

javascript - 正则表达式查找两个字符串之间的字符串,不包括外部字符串

php - 将货币格式的字符串转换为 float

regex - awk 解析邮件日志中的唯一 IP 地址

perl - 为什么 Perl open() 文档使用两种不同的 FILEHANDLE 样式?