Bagaimana cara menulis for loop in bash


Jawaban:


104

Dari situs ini :

for i in $(seq 1 10);
do
    echo $i
done

10
Perlu disebutkan bahwa kisaran yang ditentukan di sini bersifat inklusif . Maksud saya, Anda akan melihat seluruh rentang (1 hingga 10) dicetak ke konsol.
Jamie


34

Pesta itu for terdiri dari variabel (iterator) dan daftar kata-kata yang akan diiterasi oleh iterator.

Jadi, jika Anda memiliki daftar kata terbatas, masukkan saja ke dalam sintaks berikut:

for w in word1 word2 word3
do
  doSomething($w)
done

Mungkin Anda ingin mengulang beberapa angka, sehingga Anda dapat menggunakan seqperintah untuk membuat daftar angka untuk Anda: (dari 1 hingga 100 misalnya)

seq 1 100

dan gunakan di loop FOR:

for n in $(seq 1 100)
do
  doSomething($n)
done

Perhatikan $(...)sintaksnya. Ini adalah perilaku bash, ini memungkinkan Anda untuk meneruskan output dari satu perintah (dalam kasus kami dari seq) ke yang lain (the for)

Ini sangat berguna ketika Anda harus mengulang semua direktori di beberapa jalur, misalnya:

for d in $(find $somepath -type d)
do
  doSomething($d)
done

Kemungkinannya tidak terbatas untuk menghasilkan daftar.


2
Jawaban yang bagus, tetapi Anda mungkin ingin memasukkan for ((i = 0; i <MAX; i ++)); doSomething ($ i); varian dilakukan juga. Saya pikir ini umumnya lebih disukai daripada varian for i in $ (seq 0 MAX) karena yang terakhir pertama-tama akan menghasilkan semua angka dari 0 hingga MAX sebelum benar-benar menjalankan loop.
mweerden

30

Bash 3.0+ dapat menggunakan sintaks ini:

for i in {1..10} ; do ... ; done

..which menghindari pemijahan program eksternal untuk memperluas urutan (seperti seq 1 10).

Tentu saja, ini memiliki masalah yang sama dengan for(())solusinya, terkait dengan bash dan bahkan versi tertentu (jika ini penting bagi Anda).


14

Coba bashbantuan bawaan:


$ help for

for: for NAME [in WORDS ... ;] do COMMANDS; done
    The `for' loop executes a sequence of commands for each member in a
    list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
    assumed.  For each element in WORDS, NAME is set to that element, and
    the COMMANDS are executed.
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
    Equivalent to
        (( EXP1 ))
        while (( EXP2 )); do
            COMMANDS
            (( EXP3 ))
        done
    EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is
    omitted, it behaves as if it evaluates to 1.


5
#! /bin/bash

function do_something {
   echo value=${1}
}

MAX=4
for (( i=0; i<MAX; i++ )) ; {
   do_something ${i}
}

Berikut adalah contoh yang juga dapat berfungsi di shell lama, namun tetap efisien untuk jumlah besar:

Z=$(date) awk 'BEGIN { for ( i=0; i<4; i++ ) { print i,"hello",ENVIRON["Z"]; } }'

Tapi semoga berhasil melakukan hal-hal yang berguna di dalam awk: Bagaimana cara menggunakan variabel shell dalam skrip awk?


2
Saya tidak menyadarinya sebelumnya, tetapi sintaks yang serupa ditampilkan di salah satu jawaban sebelumnya. Yang unik di sini adalah penggunaan kurung kurawal bukan tipikal do/ donepair.
Brent Bradburn

4

Saya biasanya suka menggunakan sedikit varian pada standar for loop. Saya sering menggunakan ini untuk menjalankan perintah pada serangkaian host jarak jauh. Saya memanfaatkan ekspansi brace bash untuk membuat loop yang memungkinkan saya membuat loop-for non-numerik.

Contoh:

Saya ingin menjalankan perintah uptime di frontend hosts 1-5 dan backend hosts 1-3:

% for host in {frontend{1..5},backend{1..3}}.mycompany.com
    do ssh $host "echo -n $host; uptime"
  done

Saya biasanya menjalankan ini sebagai perintah satu baris dengan titik koma di ujung baris, bukan versi yang lebih mudah dibaca di atas. Pertimbangan penggunaan utama adalah bahwa tanda kurung memungkinkan Anda menentukan beberapa nilai yang akan dimasukkan ke dalam string (misalnya, hasil pra {foo, bar} posting di prefoopost, prebarpost) dan memungkinkan penghitungan / urutan dengan menggunakan titik ganda (Anda dapat menggunakan a. .z dll.). Namun, sintaks titik ganda adalah fitur baru dari bash 3.0; versi sebelumnya tidak akan mendukung ini.


Terkait dengan ini, bagaimana jika $ host var adalah baris kosong secara tidak sengaja? Itu masih akan menembakkan ssh. Jadi, bagaimana cara menghindarinya? Dalam kasus saya, saya melakukan sesuatu yang berbeda sehingga jawaban Anda akan membantu saya. Saya mencoba memeriksa Gmail untuk pesan baru, dan jika ditemukan, kirim SMS dari dan subjek. Pertanyaan saya diberi label "Menghubungkan Dua Perintah Bash" jika Anda ingin membacanya.
Volomike

Saya tidak percaya Anda akan mendapatkan $ host var kosong. Ini karena contoh di atas menggunakan ekspansi brace. Perulangan for secara eksplisit menyetel variabel $ host ke nilai: frontend1.mycompany.com frontend2.mycompany.com. . backend1.mycompany.com Tetapi jika Anda melihat cara untuk memiliki nilai null; Saya tertarik untuk mengetahuinya. Anda dapat menjalankan ssh di dalam pengujian bersyarat jika itu adalah masalah.
terson

1

jika Anda hanya tertarik dalam bash, solusi "untuk ((...))" yang disajikan di atas adalah yang terbaik, tetapi jika Anda menginginkan sesuatu yang sesuai dengan POSIX SH yang akan bekerja pada semua unit, Anda harus menggunakan "expr" dan "while", dan itu karena "(())" atau "seq" atau "i = i + 1" tidak portabel di antara berbagai shell


0

Saya menggunakan variasi ini sepanjang waktu untuk memproses file ...

untuk file di * .log; lakukan echo "Lakukan hal-hal dengan: $ files"; echo "Lakukan lebih banyak hal dengan: $ files"; selesai;

Jika Anda tertarik untuk memproses daftar file, lihat opsi -execdir untuk file .


Saya pikir maksud Anda opsi -execdir untuk menemukan
Dijeda sampai pemberitahuan lebih lanjut.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.