gawk / awk: piping date to getline *sometimes* won't work

无人久伴 提交于 2019-11-30 20:22:44
vladr

Whenever you open a pipe or file for reading or writing in awk, the latter will first check (using an internal hash) whether it already has a pipe or file with the same name (still) open; if so, it will reuse the existing file descriptor instead of reopening the pipe or file.

In your case, all entries which end up as undefined are actually duplicates; the first time that they are encountered (i.e. when the corresponding command date "..." -d "..." is first issued) the proper result is read into x. On subsequent occurrences of the same date, getline attempts to read a second, third etc. lines from the original date pipe, even though the pipe has been closed by date, resulting in x no longer being assigned.

From the gawk man-page:

NOTE: If using a pipe, co-process, or socket to getline, or from print or printf within a loop, you must use close() to create new instances of the command or socket. AWK does not automatically close pipes, sockets, or co-processes when they return EOF.

You should explicitly close the pipe every time after you have read x:

close("date \"+%Y-%m-%d\" -d " $1)

Incidentally, would it be OK to sort and uniq uBXr0r15.txt before piping into awk, or do you need the original ordering/duplication?

Though I love awk it is not necessary for this.

tr -d '"' < uBXr0r15.txt | date +%Y-%m-%d -f -

 gawk 'BEGIN{
       m=split("January|February|March|April|May|June|July|August|September|October|November|December",d,"|")
       for(o=1;o<=m;o++){
          months[d[o]]=sprintf("%02d",o)
       }
       FS="[, ]"
    }
    {
      gsub(/["]/,"",$1)
      gsub(/["]/,"",$4)
      t=mktime($4" "months[$1]" "$2" 0 0 0")
      print strftime("%Y-%m-%d",t)
    }' uBXr0r15.txt

doing everything inside gawk will be faster than calling external commands.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!