7

我正在尝试将日期从一种格式转换为另一种格式:例如从“2005 年 10 月 29 日”到 2005-10-29。我有一个包含 625 个日期的列表。我使用 awk。

转换工作 - 大多数时候。然而,有时转换根本不会发生,并且应该保存(转换后的)日期的变量仍未定义。

这总是发生在完全相同的行上。在那些奇怪的行的日期上显式地(从 Bash shell)运行“日期”可以正常工作(日期被正确转换)。-- 这些行的文本内容并不重要。

为什么会出现这种行为,我该如何修复我的脚本?
她是:

awk 'BEGIN { FS = "unused" } { 
  x = "undefined";
  "date \"+%Y-%m-%d\" -d " $1 | getline x ;
  print $1 " = " x
}' uBXr0r15.txt \
 > bug-out-3.txt

如果要重现此问题:

  1. 下载此文件:uBXr0r15.txt
  2. 运行 awk 脚本。
  3. 在 bug-out-3.txt 中搜索“未定义”。
    (“未定义”在我的电脑上找到了 122 次。)

然后您可以再次运行该脚本,并且(在我的计算机上)bug-out-3.txt 保持不变——完全相同的日期未定义。

(Gawk 版本 3.1.6,Ubuntu 9.10。)

亲切的问候,马格努斯

4

3 回答 3

11

每当您打开管道或文件进行读取或写入时awk,后者将首先检查(使用内部哈希)是否已经打开了同名的管道或文件(仍然);如果是这样,它将重用现有的文件描述符,而不是重新打开管道或文件。

在您的情况下,所有最终的条目undefined实际上都是重复的;第一次遇到它们时(即date "..." -d "..."第一次发出相应的命令时),将正确的结果读入x. 在同一日期的后续出现中,getline尝试从原始date管道读取第二、第三等行,即使该管道已由 关闭date,导致x不再被分配。

gawk手册页:

注意:如果使用管道、协同进程或套接字来获取行,或者从循环中的 print 或 printf,您必须使用 close() 来创建命令或套接字的新实例。AWK 在返回 EOF 时不会自动关闭管道、套接字或协同进程。

close每次阅读后,您都应该明确管道x

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

顺便说一句,在管道进入之前是否可以sort,或者您是否需要原始订购/复制?uniq uBXr0r15.txtawk

于 2010-03-06T04:07:51.750 回答
3

虽然我喜欢 awk 但这不是必需的。

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

于 2010-03-06T04:02:23.163 回答
3
 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

在 gawk 中做任何事情都会比调用外部命令更快。

于 2010-03-06T04:25:37.920 回答