You call many external commands (cut, sed etc.) which all take take to start a sub process and this is what is costing you.
I'm aware that date -d
is not available in all implementations. What OS are you using?
Trying to avoid being OS specific (and not the neatest code) could you consider this:-
$ cat test.txt
2011-03-01
2011-03-01
2011-03-01
2011-03-01
2011-03-01
2011-03-02
2011/03/02
$ (IFS=-;tr "\/" "-" < test.txt | while read d m Y
> do
> echo "I got \$d=\"$d\", \$m=\"$m\" and \$Y=\"$Y\""
> done)
I got $d="2011", $m="03" and $Y="01"
I got $d="2011", $m="03" and $Y="01"
I got $d="2011", $m="03" and $Y="01"
I got $d="2011", $m="03" and $Y="01"
I got $d="2011", $m="03" and $Y="01"
I got $d="2011", $m="03" and $Y="02"
I got $d="2011", $m="03" and $Y="02"
$
If you can be sure that you don't actually have any /
as date separators in your input (as you posted, possibly in error) then it simplifies to just:-
$ (IFS=- ; while read d m Y
> do
> echo "I got \$d=\"$d\", \$m=\"$m\" and \$Y=\"$Y\""
> done <test.txt)
I'm not quite sure what you are trying with the remainder. Are you trying to validate that it is an acceptable date?
If you are sure you are getting just numerics, that might be better as a case
statement like this:-
case $m in
01) mxd=31 ;;
02) ((a=($Y%4)/$Y)) 2>/dev/null ;; # Handles leap year
03) mxd=31 ;;
04) mxd=30 ;;
05) mxd=31 ;;
06) mxd=30 ;;
07) mxd=31 ;;
08) mxd=31 ;;
09) mxd=30 ;;
10) mxd=31 ;;
11) mxd=30 ;;
12) mxd=31 ;;
*) echo "Invalid month" ; exit 99
esac
if [ $d -gt $mxd -o $d -lt 1 ]
then
echo "Invalid day" ; exit 99
fi
Of course, if you are just looking for the right format, then:-
grep -v "^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" test.txt
I hope that this helps,
Robin
Liverpool/Blackburn
UK