I am trying to create a script that can transform an output from a Cisco switch showing last input and output on an interface to a useful format. This is to be able to know what interfaces hasn't been used, let's say, the last 6 months. Cisco just says that an interfaces last input was 10w4d.What I have come to so far is an input-file like this:FastEthernet0/4,3 days ago,3 days agoFastEthernet0/8,46 years ago ,46 years ago FastEthernet0/10,46 years ago ,46 years ago FastEthernet0/11,46 years ago ,46 years ago FastEthernet0/12,08:47:53,04:00:32FastEthernet0/13,1 year ago 46 weeks ago ,1 year ago 46 weeks ago FastEthernet0/14,46 years ago ,46 years ago FastEthernet0/15,13 weeks ago 4 days ago ,13 weeks ago 4 days ago FastEthernet0/16,46 years ago ,46 years ago FastEthernet0/18,46 years ago ,46 years ago FastEthernet0/19,46 years ago ,46 years ago FastEthernet0/20,46 years ago ,46 years ago FastEthernet0/22,46 years ago ,1 year ago 50 weeks ago FastEthernet0/24,46 years ago ,46 years agoI have set all interfaces that has the status of never on last input and output to 46 years ago, so I can get a valid date. And yes, I do have a record of uptime to be able to take that into account.My issue now is that I am trying to convert that into a valid date. Doing that through awk and xargs works fine, if I do like this:awk -F, '{print $2}' tst | xargs -i date -d {} +%Y-%m-%dI get a response like this:2016-08-181970-08-211970-08-211970-08-212016-08-212014-10-031970-08-212016-05-181970-08-211970-08-211970-08-211970-08-211970-08-211970-08-21But if I do like this, which in my mind should give the same result:awk -F, -v OFS=, '{    cmd2=(date \+'%Y-%m-%d'\ -d \$2 \)    cmd2|getline d2    print cmd2,d2}' tstI get a response like this:date +%Y-%m-%d -d 3 days ago,2016-08-18date +%Y-%m-%d -d 46 years ago ,1970-08-21date +%Y-%m-%d -d 46 years ago ,1970-08-21date +%Y-%m-%d -d 46 years ago ,1970-08-21date +%Y-%m-%d -d 08:47:53,2016-08-21date +%Y-%m-%d -d 1 year ago 46 weeks ago ,2014-10-03date +%Y-%m-%d -d 46 years ago ,2014-10-03date +%Y-%m-%d -d 13 weeks ago 4 days ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18date +%Y-%m-%d -d 46 years ago ,2016-05-18I added the cmd2 to the print command just now to see what it was trying to do. Just running that command gives me the correct date.I guess I have missed something simple, but after trying over and over again for 3-4 hours now I would like to have another set of eyes on it.Anybody out there that can point me in the right direction?Updated! With just three lines of the input-file I wasn't getting any issues myself, as Stephen also pointed out. Sorry for posting an untested scenario.
Getting wrong response from date through awk
linux;awk;date
When you do:cmd = some commandcmd | getline d2cmd | getline d2in awk, the first getline gets the first line (record) of the output of cmd (cmd is then started upon that first getline), and the second one gets the second line. Upon reaching the end of the output, getline returns 0.In your case of cmd = date -d \46 years ago\, since that command only outputs one line, the first getline returns that line in d2 (and a positive number), but the second reaches eof, so returns 0 and leaves d2 untouched.Here, you'd need: cmd | getline d2; close(cmd)So cmd be run each time.Or store the output of cmd in a hash to avoid running the same command several times with the same arguments, likeif (!($2 in cache)) {cmd=...; cmd | getline cache[$2]; close(cmd)}print cache[$2]It's still a good idea to close cmd there to avoid leaving a great number of file descriptors open.Note the ambiguity in close(cmd) when cmd is used both for getline < cmd and cmd | getline. Does it close the cmd command or the cmd file or both?$ cat test.awkBEGIN{  OFS=,  getline a1 < uname  uname | getline b1  close(uname)  getline a2 < uname  uname | getline b2  print a1,b1,a2,b2}$ echo test > uname$mawk -f test.awktest,Linux,test,Linux$bwk-awk -f test.awktest,Linux,test,Linux$gawk -f test.awktest,Linux,,Linux$busybox awk -f test.awktest,,test,(bwk-awk being the one maintained by Brian Kernighan (the k in awk), the behaviour is similar with awk implementations based on that like Solaris nawk or FreeBSD awk).See how busybox awk doesn't let you use uname as both a file and command with getline and how close(uname) doesn't close the uname file in gawk.So, it's a good idea to make sure you don't use a file and command with the same name at the same time. You can add a \n at the beginning or end of a command to make it unlikely that it be confused with a file.Like: awk 'BEGIN {getline foo < $ENVIRON[FILE]; uname\n | getline system}'would avoid the problem if $FILE happens to be uname (not if $FILE is uname<newline> but that's less likely).