Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to match dates of the form

Monday May 26

My attempt to do this is the following:

/(.*day Jan.*|Feb.*|Mar.*|Apr.*|May|Jun.*|Jul.*|Aug.*|Sep.*|Oct.*|Nov.*|Dec.* [1-31])/

The regex form in UNIX and Perl seem to be the same, so this is why I ask it here.

share|improve this question
    
I wouldn't say that UNIX or better to say POSIX regex is the same as Perl regex. In shell you actually do not use regular expresions, but you use glob pattern matching. Perl regular expressions are much more powerful. And this wouldn't example wouldn't work as expected in Perl. –  Neven May 31 at 23:22

2 Answers 2

up vote 1 down vote accepted

Perl regular expressions and Perl Compatible Regular Expressions are slightly different to the POSIX "basic" or "extended" regex that utilities like grep implement. Wikipedia is probably the best place to get an intro to the differences. PCRE support can be available in places other than Perl, like GNU grep -P.

For a basic regex:

echo "Monday Feb 23" | grep '^[[:alpha:]]+day (Jan\|Feb\|Mar\|Apr\|May\|Jun\|Jul\|Aug\|Sep\|Oct\|Nov\|Dec)[[:alpha:]]* [1-9][0-9]?$'

For a Perl regex with named capture groups:

$re = qr/
  ^                      # Start of string
  (?<day>[[:alpha:]]+day)  # Match one or more alpha characters before "day". 
  \s+                    # One or more whitespace chars
  (?<month>(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[[:alpha:]]*) # Months
  \s+                    # One or more whitespace chars
  (?<number>\d{1,2})     # 1-2 digits.   
  $                  # End of string. 
/x;

print "match\n" if ( "Thursday May 1" =~ $re );
print "match\n" if ( "Monday February 23" =~ $re );
print "no match\n" if ( "Wednesday May 123" !~ $re );
print "no match\n" if ( "Thursday Blarg 23" !~ $re );
print "no match\n" if ( "Inglebert January 5" !~ $re );

The x modifier after the delimeters // allows the use white space and comments so your regular expressions are more readable.

A successful match will store each field in it's own capture group which is accessible via the match hash $+

printf "day [%s] month [%s] day of month [%s]\n", $+{day}, $+{month}, $+{number}

You could get a bit more technical with the number match if you want it to be exact.

(?<number>[1-9]|[12][0-9]|3[01])

If you are getting to this level you should be looking at using a date parsing module rather than regular expressions as dates are way too complex. For example, Apr 31 or February in general.

share|improve this answer

Your input will match against following pattern in Perl. Here is Perl oneliner:

perl -e 'if("Monday February 23" =~ /(^.*day (Jan.*|Feb.*|Mar.*|Apr.*|May|Jun.*|Jul.*|Aug.*|Sep.*|Oct.*|Nov.*|Dec.*) [1-31]+)/) {print $1}'
share|improve this answer
1  
Although OP used .*, it allows a bit to much leway, like "FDAFDASFSDAFASDF#$%#@$#@$@# day Jan#@$E#@KFLDSKFDSLKLFDA. Also [1-31]+ is not doing what you think. It's matching the range 1-3 and the number 1, 1 or more times. –  mtm Jun 1 at 6:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.