在bash中使用bash循环迭代日期 - for((...))无法正常工作

时间:2015-06-01 17:48:37

标签: linux bash date scripting

我正在尝试创建日期列表。下面这个脚本适用于没有空格的简单日期。

datestart="2013-06-01 00:00:00"
dateend="2013-07-05 00:00:00"
for (( date1="$datestart"; date1 != "$dateend"; )); do
    date1="$(date --date=""$date1" + 1 days" +'%Y-%d-%m %H:%M:%S')";        
    echo "$date1";
done

当我使用数据字符串(包含WHITE SPACE)时,datestart =“2013-06-01 00:00:00”和日期格式如+'Y-%m-%d%H:%M: %S'

-bash: ((: date1=2013-06-01 00:00:00: syntax error in expression (error token is "00:00:00")

我收到以下错误:

Range

我想我没有正确引用我的变量。我已经摆弄和摆弄,现在我在这里。如何在for循环中正确引用变量?

3 个答案:

答案 0 :(得分:2)

没办法,bash三表达式for循环期望aritmetic表达式。看到这个链接:

http://wiki.bash-hackers.org/syntax/ccmd/c_for

使用经典的“while”循环。

<强>附录

你可以使用epoch中的秒来允许算术,例如:

datestart=$(date --date="2013-06-01 00:00:00" +%s)
dateend=$(date --date="2013-07-05 00:00:00" +%s)
for (( date1=$datestart; date1 != $dateend; date1+=86400 )); do
    date --date=@$date1
done

但要注意没有86400秒的日子。

答案 1 :(得分:2)

这应该适合你:

datestart="2013-06-01 00:00:00"
dateend="2013-07-05 00:00:00"

date1="$datestart"
while [[ "$date1" != "$dateend" ]]; do
   date1="$(date -u --date="$date1 tomorrow" '+%Y-%m-%d %H:%M:%S')"
   echo "$date1"
done

Working Demo

  1. ((...))仅用于算术运算。请改用while循环。
  2. 无需使用$date
  3. 的嵌套引号
  4. 使用tomorrow获取下一个日期
  5. 在为year-month-date
  6. 指定下一个日期时使用正确的date1格式

答案 2 :(得分:1)

关于你的报价是否合适,你是对的。你有:

date1="$(date --date=""$date1" + 1 days" +'%Y-%d-%m %H:%M:%S')";        

但是你用非常奇怪的方式进出双引号。一个快速的解决方案可能是切换到单引号,如果它们在双引号内,则不会隔离变量:

date1="$(date --date="'$date1' + 1 days" +'%Y-%d-%m %H:%M:%S')";        

至于另一部分......让我们回顾一下bash手册页上的内容:

for (( expr1 ; expr2 ; expr3 )) ; do list ; done
      First, the arithmetic expression expr1 is evaluated according to
      the  rules  described  below  under  ARITHMETIC EVALUATION. ...

如果您查看手册页的ARITHMETIC EVALUATION部分,您会发现包含/ bin / test或{{1}的各种测试}} 能跑。这些内容将在手册页的下一部分[[ ... ]]中介绍。

如果你想使用CONDITIONAL EXPRESSIONS循环,那么@ pasaba建议使用纪元秒也是我也要遵循的,以便坚持算术。像这样:

for

要考虑闰年和闰秒等,您可以放心地使用Linux #!/bin/bash datestart="2013-06-01 00:00:00" dateend="2013-07-05 00:00:00" e_start=$(date -d "$datestart" '+%s') e_end=$(date -d "$dateend" '+%s') for (( date1=$e_start; date1 < $e_end; date1+=86400 )); do echo -n "$date1 "; date -d "@$date1" '+%Y-%m-%d' done 命令,并像以前一样评估循环中的date

$date1

嵌套for (( date1=$e_start; date1 < $e_end; )); do date1=$(date -d "$(date -d "@$date1") + 1 day" '+%s') echo -n "$date1 "; date -d "@$date1" '+%Y-%m-%d' done 命令是必需的,因为Linux的date命令不允许您使用相对日期(&#34; + 1day&#34;或&#34 ;明天&#34;)当原始日期被指定为date的纪元时。 (我很想知道我是否错了。)

我意识到您的问题被标记为&#34; Linux&#34;,但我注意到将来的搜索,这是@命令的非可移植(仅限Linux)使用,所以如果你想让这个脚本在FreeBSD,NetBSD,OSX等中运行,你需要检查它们的用法。以下适用于FreeBSD:

date