Cú pháp cho một vòng lặp Bash vô hạn một dòng


635

Tôi gặp khó khăn khi đưa ra sự kết hợp đúng của dấu chấm phẩy và / hoặc niềng răng. Tôi muốn làm điều này, nhưng như một lớp lót từ dòng lệnh:

while [ 1 ]
do
    foo
    sleep 2
done

4
thay thế dòng mới bằng dấu chấm phẩy. Các công việc tương tự cho các vòng lặp.
Tom

23
@Tom: không phải lúc nào cũng hoạt động. sau khi làm, bạn phải có lệnh đầu tiên, không phải dấu chấm phẩy
Stefano Borini

Câu trả lời:


1232
while true; do foo; sleep 2; done

Nhân tiện, nếu bạn gõ nó dưới dạng đa dòng (như bạn đang hiển thị) tại dấu nhắc lệnh và sau đó gọi lịch sử bằng mũi tên lên, bạn sẽ nhận được nó trên một dòng duy nhất, được chấm câu chính xác.

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

2
"nếu bạn nhập nó dưới dạng đa dòng (như bạn đang hiển thị) tại dấu nhắc lệnh và sau đó gọi lịch sử bằng mũi tên lên, bạn sẽ nhận được nó trên một dòng duy nhất, được chấm câu chính xác." không đúng với tôi
Vincent Scheib

@VincentScheib, kiểm tra cmdhisttùy chọn nếu bạn đang sử dụng bash?
Alok Singhal

Thông minh! Hoạt động hoàn hảo trên Mavericks (Mac OS-X 10.9) và cho phép tôi tiếp tục chạy vpn. Kết nối bị ngắt kết nối sau một vài giờ với lỗi cookie xấu. Vì vậy, tôi đặt lệnh openconnect trong tập lệnh shell, sudo su để trở thành root và sử dụng dòng cmd này: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts

170

Cũng có thể sử dụng lệnh ngủ trong điều kiện. Làm một lớp lót trông imho sạch sẽ hơn.

while sleep 2; do echo thinking; done

16
Vâng, điều này không chỉ thay đổi cú pháp - nó sẽ thực thi lệnh sau khi ngủ. Trong câu trả lời trước, lệnh được thực thi ngay lập tức. Chỉ cần một cái gì đó để lưu ý.
DanGordon

@DanGordon while echo thinking ; do sleep 2 ; done Tất nhiên nếu lệnh [while] không thành công, vòng lặp sẽ thoát, vì vậy bạn sẽ phải while echo thinking || true ; do sleep 2 ; donequay lạiwhile true ; ...
Brian Carcich

69

Đại tràng luôn là "sự thật":

while :; do foo; sleep 2; done

15
Tại sao đại tràng luôn luôn đúng?
Jürgen Paul

8
@Pinnut Under the Sea: Từ trang bash man: (trong phần SHELL BUILTIN THÔNG TIN) : [arguments] Không có hiệu lực; lệnh không làm gì ngoài việc mở rộng đối số và thực hiện bất kỳ chuyển hướng được chỉ định nào. Mã thoát không được trả về.
Adrian W

2
cú pháp này được khuyến nghị là: là một phần của shell, tức là: là lệnh dựng sẵn shell.
avner

@analytik vậy bạn đang nói đó là điểm cộng hay điểm trừ? ;-)
Brian Carcich

33

Bạn có thể sử dụng dấu chấm phẩy để phân tách các câu lệnh:

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

3
Tôi thích câu trả lời này vì nó giải thích khi nào và tại sao; (dấu chấm phẩy) là bắt buộc.
Ông AndreasGeo

29

Bạn cũng có thể sử dụng untillệnh:

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

Lưu ý rằng ngược lại while, untilsẽ thực thi các lệnh bên trong vòng lặp miễn là điều kiện kiểm tra có trạng thái thoát không bằng không.


Sử dụng một whilevòng lặp:

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

Sử dụng một forvòng lặp:

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

Một cách khác sử dụng until:

until [ ]; do foo; sleep 2; done

Điều until ((0)); do foo; sleep 2; donenày dường như không hoạt động. Nó liên tục vô tận.
030

11

Một vòng lặp vô hạn rất đơn giản .. :)

while true ; do continue ; done

Fr câu hỏi của bạn nó sẽ là:

while true; do foo ; sleep 2 ; done

8

Tôi chỉ thích sử dụng dấu chấm phẩy cho câu lệnh WHILE và toán tử && để tạo vòng lặp làm nhiều việc ...

Vì vậy, tôi luôn luôn làm như thế này

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
Chà, việc sử dụng &&trong vòng lặp cũng giống như bất kỳ lúc nào khác thực sự không phải vậy. Bạn có cần điều thứ hai chỉ xảy ra nếu điều đầu tiên xảy ra, sau đó sử dụng đủ &&điều kiện khác ;. Thực sự, bạn muốn giữ cho nội dung của vòng lặp đó ngắn gọn và đơn giản, lý tưởng chỉ là một lệnh, do đó, một chức năng hoặc một tập lệnh.
thecoshman 7/07/2015


6

Sử dụng while:

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

Sử dụng forvòng lặp:

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

Sử dụng Recursion, (khác một chút so với ở trên, ngắt bàn phím sẽ không dừng được)

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

5

Nếu bạn muốn vòng lặp while dừng sau một số điều kiện và foolệnh của bạn trả về giá trị khác không khi điều kiện này được đáp ứng thì bạn có thể nhận được vòng lặp để phá vỡ như sau:

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

Ví dụ: nếu foolệnh đang xóa mọi thứ theo lô và nó sẽ trả về 1 khi không còn gì để xóa.

Này hoạt động tốt nếu bạn có một kịch bản tùy chỉnh mà cần phải chạy một lệnh nhiều lần cho đến khi một số điều kiện. Bạn viết kịch bản để thoát 1khi điều kiện được đáp ứng và thoát 0khi nó sẽ được chạy lại.

Ví dụ: giả sử bạn có tập lệnh python batch_update.pycập nhật 100 hàng trong cơ sở dữ liệu và trả về 0nếu có thêm thông tin cập nhật và 1nếu không có thêm. Lệnh sau sẽ cho phép bạn cập nhật hàng 100 cùng một lúc với ngủ trong 5 giây giữa các lần cập nhật:

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

và làm thế nào bạn sẽ thoát?
AK_

Bạn thực hiện foolệnh thoát với mã 1khi bạn muốn vòng lặp while bị phá vỡ. Tôi đã cập nhật câu trả lời của mình bằng một ví dụ.
Yep_It's_Me

2

Nếu tôi có thể đưa ra hai ví dụ thực tế (với một chút "cảm xúc").

Đây viết tên của tất cả các file kết thúc với ".jpg" trong thư mục 'img':

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

Điều này xóa chúng:

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

Chỉ cần cố gắng để đóng góp.


1
@JKnight - đối với những ví dụ này, bạn sẽ không làm ls -1 *.jpgrm *.jpg
Kevin Fegan

2
Cả hai không phải là vòng lặp vô hạn và không phải là vòng lặp.
Mary

2

Bạn cũng có thể thử điều này CẢNH BÁO: điều này bạn không nên làm nhưng vì câu hỏi đang yêu cầu vòng lặp vô hạn không có hồi kết ... đây là cách bạn có thể làm.

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

Tại sao bạn thậm chí sẽ làm điều đó?
gniourf_gniourf

2
bởi vì Brian Deacon đã đăng câu hỏi muốn như một vòng lặp infinte. Đó là nhiều hơn một cách để da một con mèo đó là tất cả
grepit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.