所以我想编写一个脚本来扫描订单和文件,并将这些文件的某些行粘贴到文件中。
如何让我的文件扫描指定范围而不是单数日期?
实际上,我需要更改的代码如下所示:
$curdir = "$scriptdir\\$folder";
opendir my $dir_b, "$curdir" or die "Can't open directory: $!";
my @file = grep { /$timestamp/ } readdir $dir_b;
closedir $dir_b;
现在第3行需要像这样工作
my @file = grep { /$timestamp1 to $timestamp2/ } readdir $dir_b;
谁知道如何实现这一目标? timestamp1将为20160820,timestamp2为20160903或20160830
感谢您的帮助
答案 0 :(得分:2)
您可以使用Regexp::Assemble在日期范围内的所有时间戳中构建一个模式。
use strict;
use warnings;
use Regexp::Assemble;
my $timestamp_late = 20160830;
my $timestamp_early = 20160820;
my $ra = Regexp::Assemble->new;
$ra->add( $_ ) for $timestamp_early .. $timestamp_late;
print $ra->re;
该案例的模式是:(?^:201608(?:2\d|30))
您现在可以像这样使用它:
my $pattern = $ra->re;
my @files = grep { /$pattern/ } readdir $dir_b;
它通过将多个模式组合成一个模式来工作。
Regexp :: Assemble接受任意数量的正则表达式,并将它们组合成一个正则表达式(或RE),匹配单个RE匹配的所有表达式。
因此,只需要针对一个表达式测试目标字符串,而不是使用大型表达式列表进行循环。当你有几千种模式需要处理时,这很有趣。尽最大努力产生尽可能小的图案。
我们这里的模式相当简单(它们只是字符串),但它仍然有效。结果模式的工作方式如下:
(?^: ) # non-capture group w/o non-default flags for the sub pattern
201608 # literal 201608
(?: ) # non-capture group
2\d # literal 2 followed by a digit (0-9)
| # or
30 # literal 30
解释(?^:)
in this part of perlre。
如果传入更多数字,则生成的正则表达式会有所不同。当然这不适用于日期,所以使用我简单的1 .. 9
表达式,我们可以得到所有数字。 ..
是range operator,并会针对上述情况返回列表(1, 2, 3, 4, 5, 6, 7, 8, 9)
。
因此,如果您想确保只获得有效日期,可以选择this approach或this approach。这是一个例子。
use strict;
use warnings;
use Regexp::Assemble;
use DateTime;
my $timestamp_late = DateTime->new( year => 2016, month => 9, day => 1 );
my $timestamp_early = DateTime->new( year => 2016, month => 8, day => 19 ); # -1 day
my $ra = Regexp::Assemble->new;
while ( $timestamp_early->add( days => 1 ) <= $timestamp_late ) {
$ra->add( $timestamp_early->ymd(q{}) );
}
print $ra->re;
这将持续到下个月并给出
(?^:20160(?:8(?:3[01]|2\d)|901))
,只匹配实际日期,而另一个更简单的解决方案将包括它们之间的所有数字,包括8月99日。
(?^:20160(?:8(?:2\d|3\d|4\d|5\d|6\d|7\d|8\d|9\d)|90[01]))
答案 1 :(得分:2)
Сухой27
解决方案,发布为评论
my @file = grep { /$timestamp1/ .. /$timestamp2/ } readdir $dir_b;
的一个很好的例子
答案 2 :(得分:2)
我赞成一些易于理解的简单方法。触发器很酷,但几乎没有人知道它的作用。
您无需在一次操作中执行所有操作:
my @file = grep {
my $this_date = ...;
$lower_date <= $this_date and $this_date <= $higher_date;
} @inputs;