You can actually encode your rules into a regex, which will show all possible interpretations.

(The trick is to force backtracking with a (*FAIL) )

And it highlights what hippo already told you: you get two possible results for the case of 13 digits!

IOW you need more filter rules, like ...

And then you must hope there are no more ambiguities left ...

But I think this is a good start.

use v5.12; use warnings; use Data::Dump qw/pp dd/; while (my $l = <DATA>) { chomp $l; my ($n,$desc) = split /\s*=\s*/,$l; say "--- $n"; say " $desc"; my $year = join "|", 18..22; my $month = join "|", 1..9, "01".."12"; my @res; $n =~ /^ (?: (?<year>$year) | (?<month>$month) # no month without year (?<year>$year) )? # date is optional (?<serial>\d{10}) (?<check>\d)? # check is optional $ (?{ push @res, { %+ } }) (*FAIL) /x; say pp \@res; warn "*** TOO MANY MATCHES $n***\n",pp(\@res),"\n\n" if @res > 1; warn "*** NO MATCH $n ***" if @res < 1 } __DATA__ 1231600014 = 10 digit version (just the core serial) 221231600014 = 12 digit version (minus both leading month and last + check digit) 1221231600014 = 13 digit version 2 (minus the leading zero for the +month and minus the check digit). These entries would need to be corr +ected to add the leading zero and therefore become the 14 digit versi +on 2212316000140 = 13 digit version 1 (minus the leading 2 month digit +s but including the last check digit) 01221231600014 = 14 digit version (minus the last check digit) 012212316000140 = Full 15 digit serial. This comprises of month and y +ear (0122), core serial (1231600014), check digit (0)

*** TOO MANY MATCHES 2212316000140*** [ { check => 0, serial => 1231600014, year => 22 }, { month => 2, serial => 2316000140, year => 21 }, ] --- 1231600014 10 digit version (just the core serial) [{ serial => 1231600014 }] --- 221231600014 12 digit version (minus both leading month and last check digit) [{ serial => 1231600014, year => 22 }] --- 1221231600014 13 digit version 2 (minus the leading zero for the month and minus + the check digit). These entries would need to be corrected to add th +e leading zero and therefore become the 14 digit version [{ month => 1, serial => 1231600014, year => 22 }] --- 2212316000140 13 digit version 1 (minus the leading 2 month digits but including + the last check digit) [ { check => 0, serial => 1231600014, year => 22 }, { month => 2, serial => 2316000140, year => 21 }, ] --- 01221231600014 14 digit version (minus the last check digit) [{ month => "01", serial => 1231600014, year => 22 }] --- 012212316000140 Full 15 digit serial. This comprises of month and year (0122), cor +e serial (1231600014), check digit (0) [ { check => 0, month => "01", serial => 1231600014, year => 22 }, ]

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

update

refined the month rules by substituting \d|\d\d with $month = join "|", 1..9, "01".."12";


In reply to Re: Merging multiple variations of a serial number (regex as "mini prolog") by LanX
in thread Merging multiple variations of a serial number by Doozer

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.