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

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -