【问题标题】:Bash while loop between two times两次之间的 Bash while 循环
【发布时间】: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 `]'

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

【问题讨论】:

    标签: linux bash opensuse


    【解决方案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】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-07
          • 1970-01-01
          • 2017-04-26
          • 1970-01-01
          • 2010-12-10
          • 2017-11-01
          • 1970-01-01
          相关资源
          最近更新 更多