2011-12-08 11 views
3

私はディレクトリ仕様を含むperlの文字列を持っています。文字列に、日付マスクを構成する部分文字列の個体または組み合わせが含まれている場合は、その部分文字列を抽出します。たとえば、ディレクトリの仕様は次のようになります。Perlで日付マスクを抽出する正規表現とは何ですか?

/mydir/data/YYYYMMDD 

"YYYYMMDD"文字列を抽出できます。しかし、パスのその部分は、以下の文字列のいずれかの個人または組み合わせが考えられます。

YY 
YYYY 
MM 
DD 

だから、ディレクトリ仕様文字列が読むことができる:

/mydir/data/DD/data2 

を、私は「DD」は、結果として返さたいです正規表現の比較の。これらの日付マスク文字列のうちの1つ以上を含む必要があり、その文字列が2つの "/"文字の間にあるか、文字列の最後に存在する必要がある場合、文字列をキャプチャするにはどうすればよいですか?

+1

「YY」、「DD」などのリテラル文字、または日付を表す数字と一致させることを意味しますか? – TLP

+0

@TLP良い質問です!私の解決策は数​​字で動作しますが、GregHが望むものではないかもしれません。 – choroba

+0

私は完全ではない解決策を削除したので、ここでは「ヒント」 - m {/((YYYY | YY | MM | DD){1、})/} 'は近づいていますが、また、 "YYYY/MM /"のようなケースではないと思います。しかし、多分役に立つ。 – BRFennPocock

答えて

0

私は

my ($date) = m{/([0-9]{2,8})(?:/|$)} 

を使用したいと

not(length($date) % 2) # $date has even length 

と、おそらく有効な組み合わせのためのいくつかのチェックかどうかをチェックします。

更新: OK、マスクだけではなく、番号を取得するために、あなたはこれがそうでYYDDYYまたはYYYYMMYYなどのすべての無効な組み合わせを除外しなければならない

my ($date) = m{/([YMD]{2,8})(?:/|$)}; 
my $check = $date; 
$check =~ s/YYYY/y/; 
$check =~ s/MM//; 
$check =~ s/DD//; 
print "Matches $date\n" if grep $_ eq $check, (q{}, 'y', 'YY'); 

にこれを変更することができます。 - M - D、これをマスクフィールドを想定し

#!/usr/bin/perl 
use warnings; 
use strict; 

my @paths = qw(
    /mydir/data/YYYYMMDD 
    /mydir/data/YY/data2 
    /mydir/data/YYMM/data2 
    /mydir/data/DD/data2 
); 

foreach my $path (@paths) { 
    my($date) = grep /^(([YMD])\2)+$/, split '/', $path; 
    print "$path: $date\n"; 
} 
+0

ディレクトリspec内の文字列に数値が含まれていません。それは実際に私がリストした英字(MM、DD、YY、YYYY)を含んでいます。これらの文字を含む部分文字列を抽出する必要があります。 – GregH

+0

更新されました。今すぐ動作します。 – choroba

1

私はあなたが1日1たいと、そうでない場合はそこに一つだけ「日付」の成分である、または仮定します何が必要でしょう。

my ($mask) = $path =~ m{/((?:YY){0,2} (?:MM)? (?:DD)?) (?:/|$) }x; 
1

順Yに常にある:

+0

これは私よりはるかに良い解決策です。 – tadmc

4

私がそうでなければ、それは意味がないので、YYYYYYの両方が、同じパターンで表示されてはならないという仮定を作ってるんです。

use Data::Munge qw(list2re); 
use List::MoreUtils qw(uniq); 
use Algorithm::Combinatorics qw(variations); 
use Perl6::Take qw(gather take); 

list2re 
uniq 
gather { 
    for my $n ([qw(YYYY MM DD)], [qw(YY MM DD)]) { 
     for my $k (1..scalar @$n) { 
      take map { join q(), @$_ } variations($n, $k) 
     } 
    } 
} 

この式は、正規表現(?^:DDMMYYYY|DDYYYYMM|MMDDYYYY|MMYYYYDD|YYYYDDMM|YYYYMMDD|DDMMYY|DDYYMM|DDYYYY|MMDDYY|MMYYDD|MMYYYY|YYDDMM|YYMMDD|YYYYDD|YYYYMM|DDMM|DDYY|MMDD|MMYY|YYDD|YYMM|YYYY|DD|MM|YY)を返します。 (Semi)優勝のための機能プログラミング!

+0

* "for"ループのために* "semi" *ですか? – Zaid

+0

ええ、標準のPerlの字句変数に '$ _ 'をコピーするために余分な行が2行必要で、Algolスタイルのパラメータが呪われていないため、' map'ではもっと面倒です。 - これは、perl5iを使用せずにできるだけ短くなっています。 – daxim

関連する問題