#!/usr/bin/perl use strict; use warnings; use Regexp::Common; my $dur = qr /-? # Optional leading minus. P # Required. (?=[T\d]) # Duration cannot be empty. (?:(?!-) $RE{num}{int} Y)? # Non-negative integer, Y (optional) (?:(?!-) $RE{num}{int} M)? # Non-negative integer, M (optional) (?:(?!-) $RE{num}{int} D)? # Non-negative integer, D (optional) (?:T (?=\d) # T, must be followed by a digit. (?:(?!-) $RE{num}{int} H)? # Non-negative integer, H (optional) (?:(?!-) $RE{num}{int} M)? # Non-negative integer, M (optional) (?:(?!-) $RE{num}{decimal} S)? # Non-negative decimal, S (optional) )? # Entire T part is optional /x; while () { chomp; print "$_ ", /^$dur$/ ? "matches\n" : "does not match\n"; } __DATA__ PnYnMnDTnHnMnS -P1Y P3Y3M3DT3H3M3S P3M3Y3DT3H3M3S P334Y3DT3H3M3S PT2H 5T PT P5M6DT P5M6DT9 P600T6S P1347Y P1347M P1Y2MT2H P0Y1347M P0Y1347M0D P-1347M -P1347M P1Y2MT P1Y2M P PT0S PT0.1234S