两次之间的 Bash while 循环

Posted

技术标签:

【中文标题】两次之间的 Bash while 循环【英文标题】:Bash while loop between two times 【发布时间】:2013-06-04 21:52:45 【问题描述】:

我正在尝试编写一个 bash 脚本,如果时间在某个时间之后和某个时间之前,它将循环。这是我得到的,但它给了我一个错误;

#!/bin/bash

while [ date +"%T" -gt '06:00:00' && date +"%T" -lt '21:00:00'];
  do
  ##echo `php mainstatquery.php`
  echo "Hello World";
  sleep 5;
done

这是错误

./timer.sh: line 3: [: missing `]'

如果有人能指出我正确的方向。

【问题讨论】:

【参考方案1】:

这是了解您的while 问题的简单方法:

[ 是一个实际的 Unix 命令。做ls /bin/[,你会看到的。这是/bin/test 命令的链接。从命令行执行man test 并查看可以完成的各种测试

while 所做的是执行你给它的命令,如果它返回零退出状态,while 语句被认为是真的,语句将继续。你可以这样做:

while sleep 2
do
   echo "I slept for two seconds"
done

test 命令所做的只是进行某种测试(文件测试、相等性测试等),如果语句为真则返回零,否则返回非零:

$  test 2 -gt 3
$ echo $?
1   <- That statement is false

$ [ 2 -lt 3 ]   #The test command using square brackets
$ echo $?
0  <- That statement is true.

查看test 的联机帮助页,您会看到所有有效的测试。这个:

while [ date +"%T" -gt '06:00:00' && date +"%T" -lt '21:00:00']

相同
while test date +"%T" -gt '06:00:00' && date +"%T" -lt '21:00:00'

让我们在这里做一些事情:

date + %T 不是test 命令的有效运算符。

test 命令无法在内部执行命令。您需要做的是将该命令放在$(..) 中,并可能使用引号来保证安全。因此:

while test "$(date +"%T")" -gt '06:00:00' && "$(date +"%T")" -lt '21:00:00'
&amp;&amp; 不是test 命令中的有效运算符。您可能想要的是-a,它是将test 中的两个测试串在一起的and 连词。

这会给你:

while test $(date +"%T") -gt '06:00:00' -a "$(date +"%T")" -lt '21:00:00'

有两个单独的大于测试运算符用于比较。一种用于字符串,一种用于整数。 -gt 是对整数的测试。既然是处理字符串,就需要使用&gt;

同时测试 "$(date +"%T")" > '06:00:00' -a "$(date +"%T")"

作为替代方案,您也可以使用&amp;&amp; 连词而不是-a,但&amp;&amp; 的每一侧都必须是单独的测试语句:

while test "$(date +"%T")" > '06:00:00' && test "$(date +"%T")" < '21:00:00'

现在,让我们将 test 语法转换回 [...],因为它更容易理解

while [ "$(date +"%T")" > '06:00:00' -a "$(date +"%T")" < '21:00:00' ]

while [ "$(date +"%T")" > '06:00:00' ] && [ "$(date +"%T")" < '21:00:00' ]

顺便说一下,内部的[[...]] 更好——尤其是带有&gt; 符号,因为它可以被shell 解释为文件重定向。

while [[ "$(date +"%T")" > '06:00:00' -a "$(date +"%T")" < '21:00:00' ]]

while [[ "$(date +"%T")" > '06:00:00' ]] && [[ "$(date +"%T")" < '21:00:00' ]]

【讨论】:

【参考方案2】:

你不能像那样比较整个小时。

由于您只是检查小时 (6date "+%H" 来执行此操作:

while [ $(date +"%H") -gt 06 ] && [ $(date +"%H") -lt 21 ];
  do
  ##echo `php mainstatquery.php`
  echo "Hello World";
  sleep 5;
done

还要考虑到date 表达式必须用$() 调用才能得到结果。还有你的

while [  date +"%T" -gt '06:00:00'   &&      date +"%T" -lt '21:00:00'];
       $(        )                ]  &&  [  $(        )              ^ need space

最后,逻辑条件写得不好。最好的POSIX recommended方式是:

if [ -f $VAR1 ] && [ -f $VAR2 ] && [ -f $VAR3 ]

【讨论】:

任意时间的字符串比较应该可以正常工作,只要它们采用 %T 格式,并且在一位数小时前添加前导零。 它没有。如果您尝试正确放置 OP 代码 while [ $(date +"%T") -gt "06:00:00" ] &amp;&amp; [ $(date +"%T") -lt "21:00:00" ];,您将得到 ./a: line 3: [: 00:12:27: integer expression expected 你当然是对的......我受到原始代码的影响,将-lt 视为字符串比较,但事实并非如此。如果你想比较%T,你需要像[[ $(date +%T) &gt; 06:00:00 ]]这样不那么便携的东西 好点!我不认为它会起作用:$ if [[ $(date +%T) &lt; 06:00:00 ]]; then echo yes; fi yes。如此有趣的行为,很高兴知道@WumpusQ.Wumbley【参考方案3】:

看起来你只关心时间所以:

#!/bin/bash

while [ $(date +"%k") -gt 6 -a $(date +"%k") -lt 21 ];
do
  ##echo `php mainstatquery.php`
  echo "Hello World";
  sleep 5;
done

【讨论】:

【参考方案4】:

关闭[ 命令的] 必须是单独的参数。在它前面加一个空格。

【讨论】:

以上是关于两次之间的 Bash while 循环的主要内容,如果未能解决你的问题,请参考以下文章

找出两次之间的差异

如何使用定时全局变量影响 bash while 循环?

Bash while 循环等待任务完成

Bash脚本,while循环中的多个条件

带有条件的 Bash 单行 while 循环的语法

Bash的循环结构(for和while)