Register
It is currently Fri Aug 01, 2014 1:47 am

regex to validate the date in bash


All times are UTC - 6 hours


Post new topic Reply to topic  [ 5 posts ] 
Author Message
 PostPosted: Wed May 01, 2013 7:01 pm   

Joined: Wed May 01, 2013 6:48 pm
Posts: 3
hi to all!
I 'm trying to implement afunction with a regex subpattern parentheses (year, month and day), to validate a date after a form field. my biggest challenge is to translate the regex in bash. here isthe function:

function isDate()
{
local TRUE=0
local FALSE=1
[ $# -ne 1 ] && return $FALSE;
local input=$1
#yyyy-mm-dd ; yyyy/mm/dd ; yyyy.mm.dd ; dd-mm-yyyy ; dd/mm/yyyy and dd.mm.yyyy format only
local regex="^((?<year>((?:19|20)[[:digit:]]{2}))(\/|-|\.)(?<month>(0[1-9]|1[012]))\2(?<day>(0[1-9]|[12][0-9]|3[01]))|(?<day>(0[1-9]|[12][0-9]|3[01]))(\/|-|\.)(?<month>(0[1-9]|1[012]))\2(?<year>((?:19|20)[[:digit:]]{2})))$"

if [ $input =~ $regex ]; then
# At this point, we hold the year, the month and the day of the date entered
if [ [ $day -eq 31 ] && [ $month -eq 4 || $month -eq 6 || $month -eq 9 || $month -eq 11 ] ]; then
return $FALSE; # 31st of a month with 30 days
fi
if [ $day -ge 30 && $month -eq 2 ]; then
return $FALSE; # February 30th or 31st
fi
leapcond1=`echo $(($year % 4))`
leapcond2=`echo $(($year % 100))`
leapcond3=`echo $(($year % 400))`
if [ [ $month -eq 2 && $day -eq 29 ] && ! [ [ $leapcond1 -eq 0 ] && [ [ $leapcond2 -ne 0 ] || $leapcond3 -eq 0 ] ] ]; then
return $FALSE; # February 29th outside a leap year
else
return $TRUE; #valid date
fi
else
return $FALSE; # Not a date
fi
}

may someone me to write the correct regex in bash for this function pls. thanks


Top
 Profile  
 PostPosted: Wed May 01, 2013 10:01 pm   

Joined: Mon Mar 02, 2009 3:03 am
Posts: 534
hi,

I wouldn't allow the user to enter anything else than the format I decided that it is the valid format.


Top
 Profile  
 PostPosted: Thu May 02, 2013 2:44 am   

Joined: Wed May 01, 2013 6:48 pm
Posts: 3
my regex is valid in perl, but using it in bash, it does'nt work.
that is why i need help to translate it.


Top
 Profile  
 PostPosted: Thu May 02, 2013 6:06 am   
Moderator
User avatar

Joined: Thu Oct 11, 2007 7:12 am
Posts: 229
Location: London - UK
I suggest forcing a limited format of entry and only accept dates in that format.

Experience has tought me that regex use in bash is trickier than in perl, even though as I understand it perl regex should work.
If you really need it I suggest using perl instead heh.
It's also time consuming to debug a complex regex.

DW


Top
 Profile  
 PostPosted: Mon May 06, 2013 5:49 am   

Joined: Wed May 01, 2013 6:48 pm
Posts: 3
I finally solved the problem. I think it was because I was using named groups in my regex, not supported by the bash shell.
I put the final version here, it can help someone else.

function isDate()
{
local TRUE=0
local FALSE=1
[ $# -ne 1 ] && return $FALSE;
local input=$1
local day month year leapcond1 leapcond2 leapcond3 firstBlock sep i
declare -a separators=("/" "-" "." " ");#all allowed input separators
local regex="(^(19[0-9]{2}|20[0-9]{2})([- /.])(0[1-9]|1[012])\3(0[1-9]|[12][0-9]|3[01]))|(^(0[1-9]|[12][0-9]|3[01])([- /.])(0[1-9]|1[012])\8(19[0-9]{2}|20[0-9]{2}))$"
#yyyy-mm-dd ; yyyy/mm/dd ; yyyy.mm.dd ; dd-mm-yyyy ; dd/mm/yyyy and dd.mm.yyyy format only
# i used back reference for separators so that yyyy-mm-dd and yyyy/mm/dd will be valid but not yyyy/mm-dd

if [ $input =~ $regex ]; #the input date match the regex
then
i=0
#here we check which input date separator was used
while [ $i -lt ${#separators[@]} -a "1${#sep}" -eq "1" ];
do
newval=`echo ${input//"$sep[$i]"/""}`; # we try to remove all occurences of the current separator from the input date
if [ "${#newval}" -ne "${#input}" ]; then #we compare the string lenght of the new value to the original one
sep=`echo ${sep[$i]}`; #we got it
fi
let i++;
done
firstBlock=`echo ${input} | cut -d"$sep" -f1`
# At this point, we hold the year, the month and the day of the date entered
month=`echo ${input} | cut -d"$sep" -f2`
if [ "${#firstBlock}" -eq "4" ]; then
day=`echo ${input} | cut -d"$sep" -f3`
year=`echo "$firstBlock"`
else
day=`echo "$firstBlock"`
year=`echo ${input} | cut -d"$sep" -f3`
fi
if [ [ $day -eq 31 ] && [ $month -eq 4 || $month -eq 6 || $month -eq 9 || $month -eq 11 ] ]; then
return $FALSE; # 31st of a month with 30 days
fi
if [ $day -ge 30 && $month -eq 2 ]; then
return $FALSE; # February 30th or 31st
fi
leapcond1=`echo $(($year % 4))`
leapcond2=`echo $(($year % 100))`
leapcond3=`echo $(($year % 400))`
if [ [ $month -eq 2 && $day -eq 29 ] && ! [ [ $leapcond1 -eq 0 ] && [ [ $leapcond2 -ne 0 ] || $leapcond3 -eq 0 ] ] ]; then
return $FALSE; # February 29th outside a leap year
else
return $TRUE; #valid date
fi
then
else
return $FALSE; # Not a date
fi
}


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP