Синтаксис для однострочного Bash бесконечного цикла while

427

У меня возникают проблемы с правильной комбинацией точек с запятой и/или фигурными скобками. Я хотел бы сделать это, но как однострочный из командной строки:

while [ 1 ]
do
    foo
    sleep 2
done
  • 4
    заменить символы новой строки на точки с запятой. То же самое работает для петель.
  • 21
    @Tom: это не всегда работает. после do у вас должна быть первая команда, а не точка с запятой
Теги:
loops
while-loop

11 ответов

817
Лучший ответ
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
  • 2
    «если вы наберете его как многострочное (как показано на рисунке) в командной строке, а затем вызовете историю со стрелкой вверх, вы получите ее в одной строке, правильно подчеркнутой». не было правдой для меня.
  • 0
    @ VincentScheib, проверьте опцию cmdhist если вы используете bash?
Показать ещё 5 комментариев
115

Также можно использовать команду sleep во время условия. Сделать однострочный слой более чистым imho.

while sleep 2; do echo thinking; done
  • 9
    Что ж, это больше, чем просто изменение синтаксиса - он выполнит команду после сна. В предыдущем ответе команда выполняется сразу. Просто кое-что отметить.
53

Колон всегда "истинно":

while :; do foo; sleep 2; done
  • 13
    почему двоеточие всегда верно?
  • 8
    @Pineapple Under the Sea: со страницы руководства bash: (в разделе КОМАНДЫ, ПОСТРОЕННЫЕ ОБОЛОЧКАМИ) : [arguments] Нет эффекта; команда не делает ничего, кроме расширения аргументов и выполнения любых указанных перенаправлений. Возвращается нулевой код выхода.
Показать ещё 2 комментария
22

Вы можете использовать точки с запятой для разделения операторов:

$ while [ 1 ]; do foo; sleep 2; done
  • 1
    Мне нравится этот ответ, потому что он объясняет, когда и почему; (точка с запятой) требуется.
18

Вы также можете использовать команду 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
6

Мне нравится использовать точки с запятой только для инструкции 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
  • 1
    Ну, использование && в цикле такое же, как и в любое другое время, не так ли. Нужно ли, чтобы второе происходило только в том случае, если первое происходит, тогда используйте && else ; достаточно. На самом деле вы хотите, чтобы содержимое этого цикла было коротким и простым, в идеале всего одна команда, то есть функция или скрипт.
5

Очень простой бесконечный цикл...:)

while true ; do continue ; done

Отправляй свой вопрос:

while true; do foo ; sleep 2 ; done
2

Для простого просмотра процесса используйте watch вместо

1

Вы можете попробовать это тоже

while [[ 0 -ne 1 ]]; do echo "it looping";   sleep 2; done
  • 0
    Зачем тебе это делать?
  • 1
    потому что Брайан Дикон, который разместил вопрос, хотел как бесконечный цикл. Это больше, чем один способ снять кожу с кошки, вот и все
1

Если я могу привести два практических примера (с небольшим количеством "эмоций" ).

Это записывает имя всех файлов, заканчивающихся ".jpg" в папке "img":

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

Просто пытаюсь внести свой вклад.

  • 3
    Проще сказать: for f in *.jpg; do echo $f; done
  • 1
    @JKnight - для этих примеров не могли бы вы просто выполнить ls -1 *.jpg и rm *.jpg
Показать ещё 1 комментарий
0

Если вы хотите, чтобы цикл while остановился после некоторого условия, и ваша команда foo возвращает ненулевое значение, когда это условие выполняется, вы можете заставить цикл разбиться следующим образом:

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

Например, если команда foo удаляет вещи партиями, и она возвращает 1, когда ничего не удаётся удалить.

  • 0
    и как бы вы вышли?
  • 0
    Вы выполняете команду foo с кодом 1 когда хотите, чтобы цикл while прервался. Я обновил свой ответ с примером.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню