shell - unix awk subtracting integer field from month of date field -
i have file around 10mm records. here datesample src file:
0000000566 2017/01/01 0 0000000055 2017/01/01 0 0000000109 2017/01/01 1 0000000940 2017/01/01 0 0000000566 2017/01/01 1 0000000055 2017/01/01 1 0000000109 2017/01/01 2
i need subtract last integer value off of month in date , print new value without integer, thus:
0000000566 2017/01/01 0000000055 2017/01/01 0000000109 2016/12/01 0000000940 2017/01/01 0000000566 2016/12/01 0000000055 2016/12/01 0000000109 2016/11/01
i've been having real troubles date (or gdate on macos whilst testing) , been searching in vain last couple of days.
it's either prefixing 0 , dropping m , d values:
awk '{ print (gdate -d $2 +"%y/%m/%d") }' <$src
or suffixing 0 , subtracting integer year:
awk '{ print (gdate -d $2 +-$3 months +"%y/%m/%d") }' <$src
or mashing whole thing still isn't correct:
awk '{ print gdate -d (gdate -d $2 +"%y/%m/%d") +-$3 months +"%y/%m/%d" }' <$src
i found following excellent response: increment date awk few days , months doing want, running very slow i'm assuming because of command within command.
here current awk (i'm using gdate because i'm running on macos bsd now):
awk '{ cmd=" gdate -d \"$(gdate -d \""$2"\")+\"-"$3"\"months\" \"+%y/%m/%d\" "; cmd | getline fmtdate; close(cmd); print $1, fmtdate }' <$src
so need output in performant way.
in advance guidance / rewrite.
cheers
if awk
supports time functions mktime
, strftime
(which gnu extension), can this:
awk -f'[ /]' '{print $1 " " strftime("%y/%m/%d", mktime($2" "($3-$5)" "$4" 0 0 0"))}' file
first convert date unix timestamp. mktime
accepts dates in "yyyy mm dd hh mm ss"
format, that's why need construct manually. normalization automatically, , happily convert "2017 -1 1 0 0 0"
same timestamp "2016 11 1 0 0 0"
.
after need convert timestamp "y/m/d" format , print it.
or, date arithmetic "by hand" in simple case doesn't require date normalization -- if day of month <= 28
. (for days greater 28
, 31
, need add clipping/clamping or overflowing script below, have take care of leap years, etc.)
#!/usr/bin/awk -f begin { fs = "[ /]"; } { mm = $2 * 12 + ($3 - 1) - $5; y = int(mm / 12); m = mm % 12 + 1; d = $4; printf("%s %04d/%02d/%02d\n", $1, y, m, d); }
so, idea simple. split line on spaces , slashes, can convert year/month total number of months (12 * y + m
). subtract month last column , convert total number of months year/month via divmod
operation.
output:
$ ./script.awk file 0000000566 2017/01/01 0000000055 2017/01/01 0000000109 2016/12/01 0000000940 2017/01/01 0000000566 2016/12/01 0000000055 2016/12/01 0000000109 2016/11/01
Comments
Post a Comment