在bash中进行循环日期转换

时间:2014-12-07 18:53:39

标签: bash shell

我在解决这个问题时遇到了问题。我想将日期格式“YYYY-MM-DD”转换为“YYYYmmdd”(即2011-10-04 - > 20111004)。

date -d 2011-03-19 +"%Y%m%d"

在命令行中工作,但不在while循环脚本中工作。

while循环的结果: 以下产生:

2011-03-17
date: invalid date `+%Y%m%d'

2011-03-10
date: invalid date `+%Y%m%d'

2010-07-07
date: invalid date `+%Y%m%d'

test.txt包含以下示例行:

"2014-09-08T01:49:31Z"
"2014-01-30T03:41:41Z"
"2012-05-23T16:08:45Z"
"2012-05-04T10:16:04Z"
"2012-04-05T15:27:40Z"
#!/bin/bash

while read QUERYDATE
do
  echo $QUERYDATE | sed 's/"\|T.*//g'
  echo $(date -d $QUERYDATE_CONVERT +"%Y%m%d")
done < test.txt

3 个答案:

答案 0 :(得分:2)

问题是永远不会定义QUERYDATE_CONVERT

替换:

echo $QUERYDATE | sed 's/"\|T.*//g'

使用:

QUERYDATE_CONVERT=$(echo $QUERYDATE | sed 's/"\|T.*//g')

这将导致输出:

20140908
20140130
20120523
20120504
20120405

错误消息来自何处?

考虑命令:

date -d $QUERYDATE_CONVERT +"%Y%m%d"

现在,如果未定义QUERYDATE_CONVERT,则在变量替换后,上述变为:

date -d +"%Y%m%d"

因此,字符串+"%Y%m%d"现在是-d选项的参数。由于不存在此类日期,date将显示错误消息:

date: invalid date `+%Y%m%d'

注释

  • 因为shell对其变量使用大写名称,所以最好使用shell变量的混合或小写名称。这可以确保您不会意外覆盖重要的内容。

  • 由于这里使用的替换很简单,因此可以用shell扩展替换对sed的调用,如sputnick所示。

  • 这可能不适用于您的最终应用,但在如图所示的脚本中,行:

    echo $(date -d $QUERYDATE_CONVERT +"%Y%m%d")
    

    可以替换为:

    date -d $QUERYDATE_CONVERT +"%Y%m%d"
    

替代

MarkReed指出,在bash下,管道可以替换为here-string:

QUERYDATE_CONVERT=$(sed 's/"\|T.*//g' <<<"$QUERYDATE")

here-string消除了一个过程,因此应该更有效率。由于此问题已标记为bash,因此这是一个很好的解决方案。

但是,这里的字符串不是POSIX。例如,它们不会在dash下工作,这是类似debian的系统上的默认/bin/sh。如果使用here-document,仍然可以在保持POSIX兼容性的同时消除额外的进程:

QUERYDATE_CONVERT=$(sed 's/"\|T.*//g' <<EOF
$QUERYDATE
EOF
)

答案 1 :(得分:0)

使用bash&#39; parameter expansion

#!/bin/bash

while read querydate; do
    querydate="${querydate%T*}"
    echo "$(date -d "${querydate//\"/}" +"%Y%m%d")"
done < test.txt

答案 2 :(得分:0)

#!/bin/bash

    while read QUERYDATE
    do
    echo $QUERYDATE | sed 's/"\|T.*//g'
    echo $(date -d $QUERYDATE_CONVERT +"%Y%m%d")
    done < test.txt

这段代码正在影响您的脚本

echo $QUERYDATE | sed 's/"\|T.*//g'

这只是打印从字符串中取出的日期(sed输出)但不存储它。因此变量$QUERYDATE保持不变

"2014-09-08T01:49:31Z"
"2014-01-30T03:41:41Z"
"2012-05-23T16:08:45Z"
"2012-05-04T10:16:04Z"
"2012-04-05T15:27:40Z"

要解决此问题,您可以尝试更换:

echo $QUERYDATE | sed 's/"\|T.*//g'

使用:

QUERYDATE=`echo $QUERYDATE | sed 's/"\|T.*//g'`

现在您将获得所需的输出,因为修改了非格式化日期并将其重新分配给变量QUERYDATE。

输出

20140908
20140130
20120523
20120504
20120405