代码之家  ›  专栏  ›  技术社区  ›  KajMagnus

嘎嘎声/嘎嘎声:管道日期到GetLine*有时*不起作用

  •  6
  • KajMagnus  · 技术社区  · 16 年前

    我正在尝试将日期从一种格式转换为另一种格式: 例如“2005年10月29日”到2005年10月29日。 我有625个约会的清单。我使用AWK。

    这种转换在大多数情况下都是有效的。 霍华德,有时候这种转变根本不会发生, 假设保存(转换)日期的变量仍然 未定义。

    这种情况总是发生在完全相同的行上。 在日期上显式地(从bash shell)运行“date” 在那些奇怪的行中工作良好(日期被正确转换)。 --重要的不是那些行的文本内容。

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

    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。)

    问候你,马格努斯

    3 回复  |  直到 14 年前
        1
  •  9
  •   Tim Cooper    14 年前

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

    在你的例子中,所有的条目 undefined 实际上是重复的;第一次遇到它们时(即当对应的命令 date "..." -d "..." 第一次发布)正确的结果被读入 x . 在同一日期的后续事件中, getline 试图从原文中读出第二、三行等 date 管道,即使管道已经被 日期 ,导致 X 不再被分配。

    gawk 人页:

    注意:如果使用管道、联合处理或套接字来获取行,或 从循环中的print或printf, 必须使用close()创建新的 命令或套接字的实例。awk不是自动的 关闭管道、插座或联合工艺 当他们返回EOF时。

    你应该明确 close 每次你看完之后 X :

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

    顺便问一下,可以 sort uniq uBXr0r15.txt 在进入之前 AWK ,还是需要原始订购/复制?

        2
  •  3
  •   Steven Huwig    16 年前

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

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

        3
  •  3
  •   ghostdog74    16 年前
     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中做任何事情都比调用外部命令快。