【问题标题】:Syntax for a single-line while loop in BashBash 中单行 while 循环的语法
【发布时间】:2010-11-20 07:34:00
【问题描述】:

我在想出正确的分号和/或大括号组合时遇到了麻烦。我想这样做,但作为命令行的单行:

while [ 1 ]
do
    foo
    sleep 2
done

【问题讨论】:

  • 用分号替换换行符。 for 循环也是如此。
  • @Tom:这并不总是有效。在do之后,你必须有第一个命令,而不是分号

标签: bash loops while-loop


【解决方案1】:
while true; do foo; sleep 2; done

顺便说一句,如果您在命令提示符下将其键入为多行(如您所显示的那样),然后使用向上箭头调用历史记录,您将在单行上得到正确的标点。

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done

【讨论】:

  • "如果您在命令提示符下将其键入为多行(如您所显示的那样),然后使用向上箭头调用历史记录,您将在单行上得到正确的标点。"对我来说不是真的。
  • @VincentScheib,如果您使用的是 bash,请检查 cmdhist 选项?
  • 太棒了!在 Mavericks (Mac OS-X 10.9) 上完美运行,并允许我保持 vpn 运行。几个小时后,Openconnect 会因 cookie 错误而断开连接。所以我把 openconnect 命令放在一个 shell 脚本中,sudo su 成为 root,并使用这个 cmd 行:while true; do sh /Users/myuser/bin/vpn ; done
【解决方案2】:

您可以使用分号分隔语句:

$ while [ 1 ]; do foo; sleep 2; done

【讨论】:

  • 我喜欢这个答案,因为它解释了何时以及为什么; (分号)是必需的。
【解决方案3】:

我喜欢只在 WHILE 语句中使用分号, 和 && 运算符使循环做不止一件事......

所以我总是这样做

while true ; do echo Launching Spaceship into orbit && sleep 5s && /usr/bin/launch-mechanism && echo Launching in T-5 && sleep 1s && echo T-4 && sleep 1s && echo T-3 && sleep 1s && echo T-2 && sleep 1s && echo T-1 && sleep 1s && echo liftoff ; done

【讨论】:

  • 嗯,&amp;&amp; 在循环中的使用与其他任何时候一样,真的不是吗。只有当第一件事发生时,您才需要第二件事发生,然后使用 &amp;&amp; 否则 ; 就足够了。确实,您希望循环的内容简短而简单,理想情况下只有一个命令,一个函数或一个脚本。
  • 谨慎使用sleep 中的单位,例如sleep 1h。在我的 zsh 中,它会忽略单位 h 并每 1 秒运行一次我的命令。做一个快速的man sleep 看看你的环境的sleep 命令首先支持什么。可能会让您头疼。
  • 谢谢你。我一直在寻找在“做”中运行不止一件事的正确方法
【解决方案4】:

如果我可以举两个实际的例子(有点“情感”)。

这会写入文件夹“img”中所有以“.jpg”结尾的文件的名称:

for f in *; do if [ "${f#*.}" == 'jpg' ]; then echo $f; fi; done

这会删除它们:

for f in *; do if [ "${f#*.}" == 'jpg' ]; then rm -r $f; fi; done

只是想做出贡献。

【讨论】:

  • @JKnight - 对于这些例子,你不会只做 ls -1 *.jpgrm *.jpg
  • 两者都不是无限循环,也不是while循环。
【解决方案5】:

也可以在 while 的条件下使用 sleep 命令。让单线看起来更干净恕我直言。

while sleep 2; do echo thinking; done

【讨论】:

  • 嗯,这不仅仅是改变语法——它会在睡眠之后执行命令。在上一个答案中,该命令立即执行。只是需要注意的一点。
  • @DanGordon while echo thinking ; do sleep 2 ; done 当然,如果 [while] 命令失败,则循环退出,所以你必须while echo thinking || true ; do sleep 2 ; done,然后你又回到while true ; ...
【解决方案6】:

冒号总是“真”:

while :; do foo; sleep 2; done

【讨论】:

  • 为什么冒号总是正确的?
  • @Pineapple Under the Sea:来自 bash 手册页:(在 SHELL BUILTIN COMMANDS 部分): [arguments] 无效;该命令除了扩展参数和执行任何指定的重定向之外什么都不做。返回零退出代码。
  • 这种语法被推荐为 : 是 shell 本身的一部分,即 : 是一个 shell 内置命令。
【解决方案7】:

你也可以使用until命令:

until ((0)); do foo; sleep 2; done

请注意,与while 相比,只要测试条件的退出状态不为零,until 就会执行循环内的命令。


使用while 循环:

while read i; do foo; sleep 2; done < /dev/urandom

使用for 循环:

for ((;;)); do foo; sleep 2; done

使用until的另一种方式:

until [ ]; do foo; sleep 2; done

【讨论】:

  • until ((0)); do foo; sleep 2; done 似乎不起作用。它连续无限。
【解决方案8】:

一个非常简单的无限循环.. :)

while true ; do continue ; done

你的问题是:

while true; do foo ; sleep 2 ; done

【讨论】:

    【解决方案9】:

    对于简单的过程观察,请改用watch

    【讨论】:

      【解决方案10】:

      你也可以试试 警告:你不应该这样做,但因为问题是要求无限循环......这就是你可以做到的。

      while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done
      

      【讨论】:

      • 你为什么要这么做?
      • 因为发布问题的 Brian Deacon 想要一个无限循环。给猫剥皮的方法不止一种
      • 为什么不呢?
      【解决方案11】:

      如果您希望 while 循环在某些条件后停止,并且您的 foo 命令在满足此条件时返回非零值,那么您可以像这样让循环中断:

      while foo; do echo 'sleeping...'; sleep 5; done;
      

      比如foo命令是批量删除东西,没有东西可以删除时返回1。

      如果您有一个自定义脚本需要多次运行命令直到出现某种情况,这很有效。您编写脚本以在满足条件时以1 退出,并在应再次运行时以0 退出。

      例如,假设您有一个 python 脚本 batch_update.py,它更新数据库中的 100 行,如果有更多要更新,则返回 0,如果没有更多,则返回 1。以下命令将允许您一次更新第 100 行,并在两次更新之间休眠 5 秒:

      while batch_update.py; do echo 'sleeping...'; sleep 5; done;
      

      【讨论】:

      • 你将如何退出?
      • 当您希望 while 循环中断时,您可以使用代码 1 退出 foo 命令。我已经用一个例子更新了我的答案。
      【解决方案12】:

      使用while

      while true; do echo 'while'; sleep 2s; done
      

      使用for循环:

      for ((;;)); do echo 'forloop'; sleep 2; done
      

      使用Recursion,(和上面有点不同,键盘中断不会停止)

      list(){ echo 'recursion'; sleep 2; list; } && list;
      

      【讨论】:

      • 小心使用sleep 中的单位,例如sleep 1h。在我的 zsh 中,它会忽略单位 h 并每 1 秒运行一次我的命令。做一个快速的man sleep 看看你的环境的sleep 命令首先支持什么。可能会让您头疼。
      【解决方案13】:

      您甚至不需要使用dodone。对于无限循环,我发现使用带有大括号的for 更易读。例如:

      for ((;;)) { date ; sleep 1 ; }
      

      这适用于bashzsh。不适用于sh

      【讨论】:

        【解决方案14】:

        您还可以将该循环置于后台(例如,当您需要与远程机器断开连接时)

        nohup bash -c "while true; do aws s3 sync xml s3://bucket-name/xml --profile=s3-profile-name; sleep 3600; done &"
        

        【讨论】:

          猜你喜欢
          • 2018-06-03
          • 2018-01-21
          • 2014-01-21
          • 2014-03-09
          • 2013-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多