Date Validation in Shell Script [Unix] [duplicate] - bash
I have to create a Shell Script wherein one of the parameters will be the date in the format dd/mm/yyyy. My question is, how can I check if the Date passed as parameter really follows this Date Format? I tried to use the grep command as below:
if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$'
but it didn't give the correct format because the day for example can be 33, 34, (...), that is not really the correct format. Anyone know something that can really check if the date passed really follows the format dd/mm/yyyy ?
Use date
date "+%d/%m/%Y" -d "09/99/2013" > /dev/null 2>&1
is_valid=$?
The date string must be in "MM/DD/YYYY" format.
If you do not get 0 then date is in invalid format.
The simplest solution, that still works perfectly, is the following :
if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1
...
It consists in combining 2 checks :
the first part checks that $1 is of this format : NNNN-NN-NN
the second part checks that it is a valid date
You need the two checks because :
if you don't do the first check, date will exit with code 0 even if your variable is a valid date in another format
if you don't do the second check, then you can end up with a 0 even for variables such as 2016-13-45
This function expects 2 strings,a format string, a date string
The format string uses the codes from the date command but does not include the '+'
The function returns 0 if the provided date matches the given format, otherwise it returns 1
Code (my_script.sh)
#!/bin/bash
datecheck() {
local format="$1" d="$2"
[[ "$(date "+$format" -d "$d" 2>/dev/null)" == "$d" ]]
}
date_test="$1"
echo $date_test
if datecheck "%d %b %Y" "$date_test"; then
echo OK
else
echo KO
fi
Output
$ ./my_script.sh "05 Apr 2020"
05 Apr 2020
OK
$ ./my_script.sh "foo bar"
foo bar
KO
First, check the form of the input using the regex. Then use awk to switch to mm/dd/yyyy and use date to validate. You can use the following expression in your if statement:
echo "$1" | egrep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$' && date -d "$(echo "$1" | awk 'BEGIN{FS=OFS="/"}{print $2"/"$1"/"$3}')" >/dev/null 2>&1
Simplest way for dd/mm/yyyy exactly in Bash is:
if [[ $1 == [0-3][0-9]/[0-1][0-9]/[0-9][0-9][0-9][0-9] ]]
Or
if [[ $1 =~ ^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$ ]]
How about using awk:
echo "31/12/1999" | awk -F '/' '{ print ($1 <= 31 && $2 <= 12 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }'
It prints "good" if its valid date else prints "bad"
#! /bin/bash
isDateInvalid()
{
DATE="${1}"
# Autorized separator char ['space', '/', '.', '_', '-']
SEPAR="([ \/._-])?"
# Date format day[01..31], month[01,03,05,07,08,10,12], year[1900..2099]
DATE_1="((([123][0]|[012][1-9])|3[1])${SEPAR}(0[13578]|1[02])${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..30], month[04,06,09,11], year[1900..2099]
DATE_2="(([123][0]|[012][1-9])${SEPAR}(0[469]|11)${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..28], month[02], year[1900..2099]
DATE_3="(([12][0]|[01][1-9]|2[1-8])${SEPAR}02${SEPAR}(19|20)[0-9][0-9])"
# Date format day[29], month[02], year[1904..2096]
DATE_4="(29${SEPAR}02${SEPAR}(19|20(0[48]|[2468][048]|[13579][26])))"
# Match the date in the Regex
if ! [[ "${DATE}" =~ "^(${DATE_1}|${DATE_2}|${DATE_3}|${DATE_4})$" ]]
then
echo -e "ERROR - '${DATE}' invalid!"
else
echo "${DATE} is valid"
fi
}
echo
echo "Exp 1: "`isDateInvalid '12/13/3000'`
echo "Exp 2: "`isDateInvalid '12/11/2014'`
echo "Exp 3: "`isDateInvalid '12 01 2000'`
echo "Exp 4: "`isDateInvalid '28-02-2014'`
echo "Exp 5: "`isDateInvalid '12_02_2002'`
echo "Exp 6: "`isDateInvalid '12.10.2099'`
echo "Exp 7: "`isDateInvalid '31/11/2000'`
Here's a function to do some data validation this:
# Script expecting a Date parameter in MM-DD-YYYY format as input
verifyInputDate(){
echo ${date} | grep '^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$'
if [ $? -eq 0 ]; then
echo "Date is valid"
else
echo "Date is not valid"
fi
}
`X="2016-04-21" then check for the below value being 1 or 0.
cal echo $x | cut -c 6-7 echo $x | cut -c 1-4 2>/dev/null | grep -c echo $x | cut -c 9-10
If the value is 1, then it's valid, else it's not valid.
Though the solution (if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1) of #https://stackoverflow.com/users/2873507/vic-seedoubleyew is best one at least for linux, but it gives error as we can not directly compare/match regex in if statement. We should put the regex in a variable and then we should compare/match that variable in if statement. Moreover second part of if condition does not return a boolean value so this part will also cause error.
So I have done slight modification in the above formula and this modification can also be customized further for various other formats or combination of them.
DATEVALUE=2019-11-12
REGEX='^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
if [[ $DATEVALUE =~ $REGEX ]] ; then
date -d $DATEVALUE
if [ $? -eq 0 ] ; then
echo "RIGHT DATE"
else
echo "WRONG DATE"
fi
else
echo "WRONG FORMAT"
fi
I would like to give an extended answer for a slightly different format, but this can easily be changed to the dd/mm/YY format with the answers already given; it's tested on busybox (posix shell)
This is one of the first hits for web searches similar to "busybox posix shell script date" and "test format" or "validate" etc, so here my solution for busybox (tested with 1.29.3, 1.23.1)
#!/bin/sh
##########
#
# check if date valid in busybox
# tested in busybox 1.29.3, 1.23.1
#
# call with:
# $0 <yyyymmdd>
#
##########
mydate=$1
if echo $mydate | grep -qE '20[0-9][0-9](0[1-9]|1[0-2])([012][0-9]|3[01])'; then
printf 'may be valid\n'
date +%Y%m%d -d $mydate -D %Y%m%d > /dev/null 2>&1
is_valid=$?
if [ $is_valid -ne 0 ]; then
printf 'not valid\n'
return 1
else
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
printf 'not valid, results in "%s"\n' "$mytestdate"
return 1
else
printf 'valid\n'
fi
fi
else
printf 'not valid (must be: <yyyymmdd>)\n'
return 1
fi
as in busybox (1.29.3 & 1.23.1) you have responds like:
lxsys:~# date +%Y%m%d -d 20110229 -D "%Y%m%d"
20110301
I had the need to validate the date in some better way but i wanted to rely mostly on the system itself
so with
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
...
fi
there is a second test - do we have a difference between the wanted or given format (input, $mydate) and the system interpretation (output, $mytestdate) of it ... if it's not the same, discard the date
I wrote this bash script to validate date. I can accept mont as alphanumeric.
#!/bin/bash
function isDateValid {
DATE=$1
if [[ $DATE =~ ^[0-9]{1,2}-[0-9a-zA-Z]{1,3}-[0-9]{4}$ ]]; then
echo "Date $DATE is a number!"
day=`echo $DATE | cut -d'-' -f1`
month=`echo $DATE | cut -d'-' -f2`
year=`echo $DATE | cut -d'-' -f3`
if [ "$month" == "01" ] || [ "$month" == "1" ]; then
month="Jan"
elif [ "$month" == "02" ] || [ "$month" == "2" ]; then
month="Feb"
elif [ "$month" == "03" ] || [ "$month" == "3" ]; then
month="Mar"
elif [ "$month" == "04" ] || [ "$month" == "4" ]; then
month="Apr"
elif [ "$month" == "05" ] || [ "$month" == "5" ]; then
month="May"
elif [ "$month" == "06" ] || [ "$month" == "6" ]; then
month="Jun"
elif [ "$month" == "07" ] || [ "$month" == "7" ]; then
month="Jul"
elif [ "$month" == "08" ] || [ "$month" == "8" ]; then
month="Aug"
elif [ "$month" == "09" ] || [ "$month" == "9" ]; then
month="Sep"
elif [ "$month" == "10" ]; then
month="Oct"
elif [ "$month" == "11" ]; then
month="Nov"
elif [ "$month" == "12" ]; then
month="Dec"
fi
ymd=$year"-"$month"-"$day
echo "ymd: "$ymd
dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }')
echo "dmy: "$dmy
if date --date "$dmy" >/dev/null 2>&1; then
echo "OK"
return 0
else
echo "NOK"
return 1
fi
else
echo "Date $DATE is not a number"
return 1
fi
}
if isDateValid "15-15-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "15-12-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "15-Dec-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "1-May-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "1-1-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "12-12-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
Blockquote
DATE = "$*"
[[ "${DATE}" != #(((([123][0]|[012][1-9])|3[1])?([ \/._-])(0[13578]|1[02])?([ \/._-])(19|20)[0-9][0-9])|(([123][0]|[012][1-9])?([ \/._-])\
(0[469]|11)?([ \/._-])(19|20)[0-9][0-9])|(([12][0]|[01][1-9]|2[1-8])?([ \/._-])02?([ \/._-])(19|20)[0-9][0-9])|(29?([ \/._-])02?([ \/._-])\
(19|20(0[48]|[2468][048]|[13579][26])))) ]] && echo error || echo good)
Related
Conditional statement when it comes to date format
I have to validate the inputted date from the user. The accepted date format is '+%m/%d/%Y' (04/10/1999) I also have to validate if the 1st parameter is greater than or equal to 2nd parameter which is also a date. For example: 10/04/2000 10/04/1999, this will echo '1st should be greater than 2nd' ` #operational statement if [ "$1" -gt "$2" ]; then echo "1st should be greater than 2nd" exit 255 fi #having error of integer expression expected #validate inputted date if [ "$1" -ne `date -d '+%m/%d/%Y'` ] || [ "$2" -ne `date -d '+%m/%d/%Y'` ]; then echo "Invalid. Follow [MM/DD/YY] Format" exit 255 fi #i think there is a mistake with my condition but can't figure it out.
#!/bin/sh # validation for date do case $date in [0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]);; *) echo "$date: invalid, must be MM/DD/YYYY" >&2; die=1 esac done [ "$die" ] && exit 1 # sort dates (new to old) printf '%s\n' "$1" "$2" | sort -rt / -k 3,3 -k 1,2 | sed '1ais newer than' Or instead of sort, arrange units largest to smallest, remove non-digits, and compare: printf '%s\n' "$1" "$2" | { IFS=/ read m1 d1 y1 read m2 d2 y2 if [ "$y1$m1$d1" -gt "$y2$m2$d2" ]; then echo "$1 is newer than $2" else echo "$2 is newer than $1" fi; } The question isn't tagged bash, so this is POSIX shell. If you can control the date format, you could choose YYYYMMDD, so they can be directly compared ([ "$1" -gt "$2" ]).
Convert 4 digits into a DateTime (Year + padded with minimum values)
I am writing a script to return a formatted date based on user input, which can be : 2016 2016/11 2016/11/10 2016/11/10 24 Basically I have to pad these input with the minimum possible values. (2016 returns 2016/01/01 00:00:00). I've tried doing it with date -d "2016" but this returns the time 8:16pm on today's date Many thanks!!
Here's a script that should basically do what you want to do: #!/bin/bash echo INPUT:$1 [[ "$1" == "" ]] && YEAR=2016 [[ "$1" =~ ^[0-9]{4}$ ]] && YEAR="$1" [[ $YEAR == "" ]] && YEAR=`echo "$1" | grep -Po ".*(?=/[0-9]{2}/)"` MONTH=`echo "$1" | grep -Po "(?<=[0-9]{4}/).*(?=/[0-9]{2})"` DAY=`echo "$1" | grep -Po "(?<=/[0-9]{2}/).*(?=\ )"` HR=`echo "$1" | grep -Po "(?<=[0-9]{2}\ ).*"` MIN="00" SEC="00" [[ "$MONTH" == "" ]] && MONTH="01" [[ "$DAY" == "" ]] && DAY="01" [[ "$HR" == "" ]] && HR="00" echo $YEAR/$MONTH/$DAY $HR:$MIN:$SEC Please note that this is a basic skeleton, you will have to add your own border cases and conditions.
You can use date command to get your output like below d1=date +%Y #Output is 2016 d2=date +%Y/%m #Output is 2016/11 d3=date +%Y/%m/%d #Output is 2016/11/10 d4=date +%Y/%m/%d\t%H #Output is 2016 -> \t-tab specified,if you want the whole time you can use "%X or %T" instead of "%H" echo $d1 echo $d2 echo $d3 echo $d4
Bash several and in if
Hi I have a csv file with dates like this which I want to parse with bash and check against todays date. 12-Jan-2015 Checking only day and month works good DAT=$(date '+%d %b %Y') DAY=${DAT:0:2} MON=$(echo ${DAT:3:3} | awk '{print toupper("$0");}') YEAR=${DAT:6:5} while IFS=",-" read name day month year do day=$(printf "%02d\n" "$day") month=$(echo "$month" | awk '{print toupper($0);}') year=$(printf "%04d\n" "$year") if [ "$day" -eq "$DAY" ] && [ "$month" = "$MON" ]; then echo "$name"; fi done < $SNAPDB > $SNAPTMPDB but when I try to also check the year if [ "$day" -eq "$DAY" ] && [ "$month" = "$MON" ] && [ "$year" -eq "$YEAR" ]; then Script ends with an error: line 119: 2015: command not found I´ve by now tried several writings like [[ … ]] -a and so on. but nothing did work. Thanks for help!
Use -a for 'and' and -o for 'or'. From the documentation: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html (look specifically at Table 7-2) Updated from comments: Use double brackets and parentheses: if ( [[ "$day" -eq "$DAY" ]] && [[ "$month" = "$MON" ]] && [[ "$year" -eq "$YEAR" ]] ); then`
Validate date format in a shell script
I have to create a Shell Script wherein one of the parameters will be the date in the format dd/mm/yyyy. My question is, how can I check if the Date passed as parameter really follows this Date Format? I tried to use the grep command as below: if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$' but it didn't give the correct format because the day for example can be 33, 34, (...), that is not really the correct format. Anyone know something that can really check if the date passed really follows the format dd/mm/yyyy ?
Use date date "+%d/%m/%Y" -d "09/99/2013" > /dev/null 2>&1 is_valid=$? The date string must be in "MM/DD/YYYY" format. If you do not get 0 then date is in invalid format.
The simplest solution, that still works perfectly, is the following : if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1 ... It consists in combining 2 checks : the first part checks that $1 is of this format : NNNN-NN-NN the second part checks that it is a valid date You need the two checks because : if you don't do the first check, date will exit with code 0 even if your variable is a valid date in another format if you don't do the second check, then you can end up with a 0 even for variables such as 2016-13-45
This function expects 2 strings,a format string, a date string The format string uses the codes from the date command but does not include the '+' The function returns 0 if the provided date matches the given format, otherwise it returns 1 Code (my_script.sh) #!/bin/bash datecheck() { local format="$1" d="$2" [[ "$(date "+$format" -d "$d" 2>/dev/null)" == "$d" ]] } date_test="$1" echo $date_test if datecheck "%d %b %Y" "$date_test"; then echo OK else echo KO fi Output $ ./my_script.sh "05 Apr 2020" 05 Apr 2020 OK $ ./my_script.sh "foo bar" foo bar KO
First, check the form of the input using the regex. Then use awk to switch to mm/dd/yyyy and use date to validate. You can use the following expression in your if statement: echo "$1" | egrep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$' && date -d "$(echo "$1" | awk 'BEGIN{FS=OFS="/"}{print $2"/"$1"/"$3}')" >/dev/null 2>&1
Simplest way for dd/mm/yyyy exactly in Bash is: if [[ $1 == [0-3][0-9]/[0-1][0-9]/[0-9][0-9][0-9][0-9] ]] Or if [[ $1 =~ ^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$ ]]
How about using awk: echo "31/12/1999" | awk -F '/' '{ print ($1 <= 31 && $2 <= 12 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }' It prints "good" if its valid date else prints "bad"
#! /bin/bash isDateInvalid() { DATE="${1}" # Autorized separator char ['space', '/', '.', '_', '-'] SEPAR="([ \/._-])?" # Date format day[01..31], month[01,03,05,07,08,10,12], year[1900..2099] DATE_1="((([123][0]|[012][1-9])|3[1])${SEPAR}(0[13578]|1[02])${SEPAR}(19|20)[0-9][0-9])" # Date format day[01..30], month[04,06,09,11], year[1900..2099] DATE_2="(([123][0]|[012][1-9])${SEPAR}(0[469]|11)${SEPAR}(19|20)[0-9][0-9])" # Date format day[01..28], month[02], year[1900..2099] DATE_3="(([12][0]|[01][1-9]|2[1-8])${SEPAR}02${SEPAR}(19|20)[0-9][0-9])" # Date format day[29], month[02], year[1904..2096] DATE_4="(29${SEPAR}02${SEPAR}(19|20(0[48]|[2468][048]|[13579][26])))" # Match the date in the Regex if ! [[ "${DATE}" =~ "^(${DATE_1}|${DATE_2}|${DATE_3}|${DATE_4})$" ]] then echo -e "ERROR - '${DATE}' invalid!" else echo "${DATE} is valid" fi } echo echo "Exp 1: "`isDateInvalid '12/13/3000'` echo "Exp 2: "`isDateInvalid '12/11/2014'` echo "Exp 3: "`isDateInvalid '12 01 2000'` echo "Exp 4: "`isDateInvalid '28-02-2014'` echo "Exp 5: "`isDateInvalid '12_02_2002'` echo "Exp 6: "`isDateInvalid '12.10.2099'` echo "Exp 7: "`isDateInvalid '31/11/2000'`
Here's a function to do some data validation this: # Script expecting a Date parameter in MM-DD-YYYY format as input verifyInputDate(){ echo ${date} | grep '^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$' if [ $? -eq 0 ]; then echo "Date is valid" else echo "Date is not valid" fi }
`X="2016-04-21" then check for the below value being 1 or 0. cal echo $x | cut -c 6-7 echo $x | cut -c 1-4 2>/dev/null | grep -c echo $x | cut -c 9-10 If the value is 1, then it's valid, else it's not valid.
Though the solution (if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1) of #https://stackoverflow.com/users/2873507/vic-seedoubleyew is best one at least for linux, but it gives error as we can not directly compare/match regex in if statement. We should put the regex in a variable and then we should compare/match that variable in if statement. Moreover second part of if condition does not return a boolean value so this part will also cause error. So I have done slight modification in the above formula and this modification can also be customized further for various other formats or combination of them. DATEVALUE=2019-11-12 REGEX='^[0-9]{4}-[0-9]{2}-[0-9]{2}$' if [[ $DATEVALUE =~ $REGEX ]] ; then date -d $DATEVALUE if [ $? -eq 0 ] ; then echo "RIGHT DATE" else echo "WRONG DATE" fi else echo "WRONG FORMAT" fi
I would like to give an extended answer for a slightly different format, but this can easily be changed to the dd/mm/YY format with the answers already given; it's tested on busybox (posix shell) This is one of the first hits for web searches similar to "busybox posix shell script date" and "test format" or "validate" etc, so here my solution for busybox (tested with 1.29.3, 1.23.1) #!/bin/sh ########## # # check if date valid in busybox # tested in busybox 1.29.3, 1.23.1 # # call with: # $0 <yyyymmdd> # ########## mydate=$1 if echo $mydate | grep -qE '20[0-9][0-9](0[1-9]|1[0-2])([012][0-9]|3[01])'; then printf 'may be valid\n' date +%Y%m%d -d $mydate -D %Y%m%d > /dev/null 2>&1 is_valid=$? if [ $is_valid -ne 0 ]; then printf 'not valid\n' return 1 else mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d) if [ $mydate -ne $mytestdate ]; then printf 'not valid, results in "%s"\n' "$mytestdate" return 1 else printf 'valid\n' fi fi else printf 'not valid (must be: <yyyymmdd>)\n' return 1 fi as in busybox (1.29.3 & 1.23.1) you have responds like: lxsys:~# date +%Y%m%d -d 20110229 -D "%Y%m%d" 20110301 I had the need to validate the date in some better way but i wanted to rely mostly on the system itself so with mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d) if [ $mydate -ne $mytestdate ]; then ... fi there is a second test - do we have a difference between the wanted or given format (input, $mydate) and the system interpretation (output, $mytestdate) of it ... if it's not the same, discard the date
I wrote this bash script to validate date. I can accept mont as alphanumeric. #!/bin/bash function isDateValid { DATE=$1 if [[ $DATE =~ ^[0-9]{1,2}-[0-9a-zA-Z]{1,3}-[0-9]{4}$ ]]; then echo "Date $DATE is a number!" day=`echo $DATE | cut -d'-' -f1` month=`echo $DATE | cut -d'-' -f2` year=`echo $DATE | cut -d'-' -f3` if [ "$month" == "01" ] || [ "$month" == "1" ]; then month="Jan" elif [ "$month" == "02" ] || [ "$month" == "2" ]; then month="Feb" elif [ "$month" == "03" ] || [ "$month" == "3" ]; then month="Mar" elif [ "$month" == "04" ] || [ "$month" == "4" ]; then month="Apr" elif [ "$month" == "05" ] || [ "$month" == "5" ]; then month="May" elif [ "$month" == "06" ] || [ "$month" == "6" ]; then month="Jun" elif [ "$month" == "07" ] || [ "$month" == "7" ]; then month="Jul" elif [ "$month" == "08" ] || [ "$month" == "8" ]; then month="Aug" elif [ "$month" == "09" ] || [ "$month" == "9" ]; then month="Sep" elif [ "$month" == "10" ]; then month="Oct" elif [ "$month" == "11" ]; then month="Nov" elif [ "$month" == "12" ]; then month="Dec" fi ymd=$year"-"$month"-"$day echo "ymd: "$ymd dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }') echo "dmy: "$dmy if date --date "$dmy" >/dev/null 2>&1; then echo "OK" return 0 else echo "NOK" return 1 fi else echo "Date $DATE is not a number" return 1 fi } if isDateValid "15-15-2014"; then echo "date is valid =)" else echo "bad format date" fi echo "===================" if isDateValid "15-12-2014"; then echo "date is valid =)" else echo "bad format date" fi echo "===================" if isDateValid "15-Dec-2014"; then echo "date is valid =)" else echo "bad format date" fi echo "===================" if isDateValid "1-May-2014"; then echo "date is valid =)" else echo "bad format date" fi echo "===================" if isDateValid "1-1-2014"; then echo "date is valid =)" else echo "bad format date" fi echo "===================" if isDateValid "12-12-2014"; then echo "date is valid =)" else echo "bad format date" fi
Blockquote DATE = "$*" [[ "${DATE}" != #(((([123][0]|[012][1-9])|3[1])?([ \/._-])(0[13578]|1[02])?([ \/._-])(19|20)[0-9][0-9])|(([123][0]|[012][1-9])?([ \/._-])\ (0[469]|11)?([ \/._-])(19|20)[0-9][0-9])|(([12][0]|[01][1-9]|2[1-8])?([ \/._-])02?([ \/._-])(19|20)[0-9][0-9])|(29?([ \/._-])02?([ \/._-])\ (19|20(0[48]|[2468][048]|[13579][26])))) ]] && echo error || echo good)
Unix convert Month name to number
In BASH shell scripting or using gdate, given a date like "Oct 2011" how do I convert to a year-month number format? Output should be "2011-10", for example.
mydate="Oct 2011" date --date="$(printf "01 %s" $mydate)" +"%Y-%m" The parse_datetime interface for GNU date (which is what the example uses) has lots of rules. the Oct 2011 form of the date isn't one of them, so you prepend a "01 " to the front of it and date likes it.
read mon year <<< "Oct 2012" date -d "$mon 1 $year" "+%Y-%m" Result: 2012-10
You can convert the month to a number by finding the position of the name string: #!/bin/bash month=Oct months="JanFebMarAprMayJunJulAugSepOctNovDec" tmp=${months%%$month*} month=${#tmp} monthnumber $((month/3+1)) printf "%02d\n" $monthnumber The output of the script above is: 10 Your specific string you could code: #!/bin/bash mydate="Oct 2011" monthnumber() { month=$1 months="JanFebMarAprMayJunJulAugSepOctNovDec" tmp=${months%%$month*} month=${#tmp} monthnumber=$((month/3+1)) printf "%02d\n" $monthnumber } arr=(`echo ${mydate}`); month=$(monthnumber ${arr[0]}) year=$(echo ${arr[1]}) echo "$year-$month" The output would be: 2011-10
case "`date | awk '{print $2 }'`" in Jan) MON="01" ;; Feb) MON="02" ;; Mar) MON="03" ;; Apr) MON="04" ;; May) MON="05" ;; Jun) MON="06" ;; Jul) MON="07" ;; Aug) MON="08" ;; Sep) MON="09" ;; Oct) MON="10" ;; Nov) MON="11" ;; Dec) MON="12" ;; esac echo $MON
I'm not sure if there is a shorter way of doing this, but here is one way. This is by no means fool proof. You can improve this by adding other checks to input and make the comparison case insensitive. #!/bin/ksh ### Validate input if [ $# -eq 0 ] then echo "Usage: $0 InputMonYYYY" echo "Example: $0 \"Oct 2011\"" exit 1 fi ### Read input INPUTSTR=$1 MON_STR=`echo $INPUTSTR |cut -d' ' -f1` YYYY_STR=`echo $INPUTSTR |cut -d' ' -f2` if [[ "$MON_STR" = "Jan" ]] then MON_NUM=01 elif [[ "$MON_STR" = "Feb" ]] then MON_NUM=02 elif [[ "$MON_STR" = "Mar" ]] then MON_NUM=03 elif [[ "$MON_STR" = "Apr" ]] then MON_NUM=04 elif [[ "$MON_STR" = "May" ]] then MON_NUM=05 elif [[ "$MON_STR" = "Jun" ]] then MON_NUM=06 elif [[ "$MON_STR" = "Jul" ]] then MON_NUM=07 elif [[ "$MON_STR" = "Aug" ]] then MON_NUM=08 elif [[ "$MON_STR" = "Sep" ]] then MON_NUM=09 elif [[ "$MON_STR" = "Oct" ]] then MON_NUM=10 elif [[ "$MON_STR" = "Nov" ]] then MON_NUM=11 elif [[ "$MON_STR" = "Dec" ]] then MON_NUM=12 fi echo ${YYYY_STR}-${MON_NUM}
Bash4 supports hash-tables (answer by Jim is the correct one though). Example #!/bin/bash declare -A months=( ["Jan"]="01" ["Feb"]="02" ) mydate="Jan 2011" echo ${mydate:4:8}-"${months["${mydate:0:3}"]}" Output: 2011-01
Let's kick this dead horse. If you don't care about invalid month names you can use this function I've written which is quite short (and only does 1 exec) but expects a month to be valid english 3-chars lower or upper case and only requires GNU sed and bash: m2n() { echo $((-10+$(sed 's/./\U&/g;y/ABCEGLNOPRTUVY/60AC765A77ABB9/;s/./+0x&/g'<<<${1#?}) ));} For your example I'd do: read m y <<<"$#"; echo "$y-`m2n $m`"