From: Hermann Peifer on 23 Apr 2010 07:45 On 23/04/2010 05:46, Ed Morton wrote: > > Yes, but that wouldn't solve the logic problem. You could instead use > GNU date's --date= argument or GNU awks' "mktime()" function to check if > the specified date is a real one by trying to use it as a date. > How would you do the test with GNU awks' "mktime()" function: gawk 'BEGIN{ print mktime("2010 03 32 0 0 0") print mktime("2010 04 01 0 0 0") }' 1270072800 1270072800 ? Hermann
From: Ed Morton on 23 Apr 2010 08:14 On 4/23/2010 6:45 AM, Hermann Peifer wrote: > On 23/04/2010 05:46, Ed Morton wrote: >> >> Yes, but that wouldn't solve the logic problem. You could instead use >> GNU date's --date= argument or GNU awks' "mktime()" function to check if >> the specified date is a real one by trying to use it as a date. >> > > How would you do the test with GNU awks' "mktime()" function: > > gawk 'BEGIN{ print mktime("2010 03 32 0 0 0") > print mktime("2010 04 01 0 0 0") > }' > 1270072800 > 1270072800 > I expected mktime() to return -1 for that like it does for other invalid date specs so I'm surprised by that result. I guess you'd have to do something like compare the returned value for your given date to the values returned for the next day. Ed.
From: Ed Morton on 23 Apr 2010 08:31 On 4/23/2010 7:14 AM, Ed Morton wrote: > On 4/23/2010 6:45 AM, Hermann Peifer wrote: >> On 23/04/2010 05:46, Ed Morton wrote: >>> >>> Yes, but that wouldn't solve the logic problem. You could instead use >>> GNU date's --date= argument or GNU awks' "mktime()" function to check if >>> the specified date is a real one by trying to use it as a date. >>> >> >> How would you do the test with GNU awks' "mktime()" function: >> >> gawk 'BEGIN{ print mktime("2010 03 32 0 0 0") >> print mktime("2010 04 01 0 0 0") >> }' >> 1270072800 >> 1270072800 >> > > I expected mktime() to return -1 for that like it does for other invalid > date specs so I'm surprised by that result. I guess you'd have to do > something like compare the returned value for your given date to the > values returned for the next day. > Here's what I mean by that: $ gawk 'BEGIN{ print mktime("2010 02 28 0 0 0") print mktime("2010 02 29 0 0 0") print mktime("2010 02 30 0 0 0") print mktime("2010 03 01 0 0 0") print "" print mktime("2012 02 28 0 0 0") print mktime("2012 02 29 0 0 0") print mktime("2012 02 30 0 0 0") print mktime("2012 03 01 0 0 0") }' 1267336800 <- less than first day of next month so valid 1267423200 <- equal to first day of next month so invalid 1267509600 <- greater than first day of next month so invalid 1267423200 1330408800 <- less than first day of next month so valid 1330495200 <- less than first day of next month so valid 1330581600 <- equal to first day of next month so invalid 1330581600 So, assuming you can range-check the months and years, if you find that mktime(current date) returns a value greater than or equal to mktime(1st day of next month) then you have an invalid date. Regards, Ed.
From: Bill Marcum on 22 Apr 2010 21:24 On 2010-04-23, Scott Bass <sas_l_739(a)yahoo.com.au> wrote: > > Or perhaps another alternative is to do the entire error checking in > awk. In pseudocode: > > * get date parameter from arguments > * in awk: > * split on ":" character > * check length of array - if not 2 - 4 then print error msg and exit > the script > * if two fields check hour/minute are valid else print error msg and > exit > * if three fields check day/hour/minute are valid else print error msg > and exit > * if four fields check month/day/hour/minute are valid else print > error msg and exit > > 1) Is the above pseudocode possible in awk? Yes. split is an awk function. The return value is the number of elements in the array. > 2) And would you recommend it as a good approach? Yes. > 3) If not, is there a way I can get awk to return the date parameter > split as shell variables month/day/hour/minute? > You could do it without awk. IFS=":" set $date case $# in 2) hour=$1; minute=$2 ;; 3) day=$1; hour=$2; minute=$3 ;; 4) month=$1; day=$2; hour=$3; minute=$4 ;; *) echo "error" ;; esac > Thanks for the help and advice... > > Scott
From: Ed Morton on 23 Apr 2010 12:10 On 4/22/2010 7:30 PM, Scott Bass wrote: > Hi, > > I'm writing a script (ksh) where the user enters a date parameter as > follows: > > -a "begin time" > > Job will not start until after begin time > begin time is in the form of month:day:hour:minute where > month 1-12, day is 1-31, hour is 0-23 and minute is 0-59. > At least 2 fields must be given hour:minute, if 3 fields > are given they are assumed to be day:hour:minute. > > I would like to add error checking in the script, rather than having > the called utility choke on bad dates. > > I'd like to split the user parameter into fields, then check the > fields in my script. > > In Perl, the code would be something like: > > ($month, $day, $hour, $minute) = split(/:/, $foo); > > I've also found this awk example: > > foo="12:34:56" > echo $foo | awk '{split ($0, a, ":"); print a[1]}' > > But I can't see how to get the array "a" into variables available to > the script. > > Or perhaps another alternative is to do the entire error checking in > awk. In pseudocode: > > * get date parameter from arguments > * in awk: > * split on ":" character > * check length of array - if not 2 - 4 then print error msg and exit > the script > * if two fields check hour/minute are valid else print error msg and > exit > * if three fields check day/hour/minute are valid else print error msg > and exit > * if four fields check month/day/hour/minute are valid else print > error msg and exit > > 1) Is the above pseudocode possible in awk? > 2) And would you recommend it as a good approach? > 3) If not, is there a way I can get awk to return the date parameter > split as shell variables month/day/hour/minute? > > Thanks for the help and advice... > > Scott All things considered and now that I know mktime() wouldn't be as simple a solution as I thought, here's how I'd really approach this to pass in the target date/time plus the current date/time to an awk script and let it do all the checks. Below is a start, you'd have to add the leap year logic (divide the year by 4) and use the currently unused "nowA" array to figure out if the target date is in the future (as desired) or not. Note that you need the month (30-day month?) and the year (leap year?) to do some validation on the day and specific target date (already past?). So, there's still a fair bit to do, but this should show you approach and the syntax of how to do it. Ed. $ cat tst.awk BEGIN { mths30["04"]; mths30["06"]; mths30["09"]; mths30["11"] numNowFlds = split(now,nowA,/:/) numTgtFlds = split(tgt,tgtA,/:/) validInput = 1 for (i=1; i<=numTgtFlds; i++) { if (tgtA[i] !~ /^[[:digit:]]+$/) { printf "Input field %d (%s) has non-digits.\n",i,tgtA[i] | "cat>&2" validInput = 0 } } if (numTgtFlds >= 2) { min = tgtA[numTgtFlds] hour = tgtA[numTgtFlds-1] if (numTgtFlds >= 3) { day = tgtA[numTgtFlds-2] if (numTgtFlds >= 4) { mth = tgtA[numTgtFlds-3] if (numTgtFlds >= 5) { print "Too many input fields" | "cat>&2" validInput = 0 } } } } else { print "Too few input fields" | "cat>&2" validInput = 0 } if ((min < 0) || (min > 59)) { printf "Minutes field (%s) out of range\n",min | "cat>&2" validInput = 0 } if ((hour < 0) || (hour > 23)) { printf "Hours field (%s) out of range\n",hour | "cat>&2" validInput = 0 } if (mth != "") { if ((mth >= 1) && (mth <= 12)) { gotMonth = 1 } else { printf "Months field (%s) out of range\n",mth | "cat>&2" validInput = 0 } } if (day != "") { if ((day >= 1) && (day <= 31)) { gotDay = 1 if (gotMth) { if ((mth == 2) && (day > 28)) { printf "Days field (%s) too big for month %s\n",day,mth | "cat>&2" validInput = 0 gotDay = 0 } if ((mth in mths30) && (day == 31)) { printf "Days field (%s) too big for month %s\n",day,mth | "cat>&2" validInput = 0 gotDay = 0 } } } else { printf "Days field (%s) out of range\n",day | "cat>&2" validInput = 0 } } print min, hour, day, mth | "cat>&2" if (! validInput) { print "Errors found, exiting." | "cat>&2" exit 1 } } $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="10:20" -f tst.awk 20 10 $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="07:02:28:10:20" -f tst.awk Too many input fields 20 10 28 02 Errors found, exiting. $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="02:28:10:20" -f tst.awk 20 10 28 02 $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="02:29:10:20" -f tst.awk Days field (29) too big for month 02 20 10 29 02 Errors found, exiting. $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="05:31:10:20" -f tst.awk 20 10 31 05 $ awk -v now="$(date +%Y:%m:%d:%H:%M)" -v tgt="06:31:10:20" -f tst.awk Days field (31) too big for month 06 20 10 31 06 Errors found, exiting.
|
Next
|
Last
Pages: 1 2 Prev: anchor for next position in regular expression Next: how to log comman to a file ? |