Bash'de nasıl for döngüsü yazarım


Yanıtlar:


106

Gönderen bu site :

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

10
Burada belirtilen aralığın kapsayıcı olduğundan bahsetmeye değer . Bununla, konsola yazdırılan tüm aralığı (1 ila 10) göreceksiniz demek istiyorum.
Jamie


34

Bash for, bir değişkenden (yineleyici) ve yineleyicinin yineleyeceği bir sözcük listesinden oluşur.

Dolayısıyla, sınırlı bir kelime listeniz varsa, bunları aşağıdaki söz dizimine eklemeniz yeterlidir:

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

Muhtemelen bazı sayılar boyunca yineleme yapmak istersiniz, böylece sizin seqiçin bir sayı listesi oluşturmak için komutu kullanabilirsiniz : (örneğin 1'den 100'e kadar)

seq 1 100

ve FOR döngüsünde kullanın:

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

Not $(...)sözdizimi. Bu bir bash davranışıdır, çıktıyı bir komuttan (bizim durumumuzda seq) diğerine (the for) geçirmenize izin verir.

Bu, bazı yollardaki tüm dizinleri yinelemeniz gerektiğinde gerçekten yararlıdır, örneğin:

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

Listeleri oluşturmak için olasılıklar sonsuzdur.


2
Güzel cevap, ancak for ((i = 0; i <MAX; i ++)); do doSomething ($ i); varyantı da yaptı. Bunun genellikle for i in $ (seq 0 MAX) varyantına tercih edildiğini düşünüyorum çünkü ikincisi, döngüyü fiilen yürütmeden önce 0'dan MAX'a kadar tüm sayıları üretecektir.
mweerden

30

Bash 3.0+ şu sözdizimini kullanabilir:

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

.. bu, diziyi genişletmek için harici bir program (örneğin seq 1 10) üretmekten kaçınır .

Tabii ki, bu for(())çözümle aynı soruna sahiptir, bash'a ve hatta belirli bir versiyona bağlı (bu sizin için önemliyse).


14

Yerleşik bashyardımı deneyin :


$ 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}
}

İşte eski kabuklarda da işe yararken, büyük sayılar için verimli olmaya devam eden bir örnek:

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

Ama içinde yararlı şeyler yapmakta bol şans awk: Bir awk komut dosyasında kabuk değişkenlerini nasıl kullanabilirim?


2
Daha önce fark etmemiştim, ancak önceki cevaplardan birinde benzer bir sözdizimi gösteriliyor. Buradaki benzersiz şey, tipik do/ doneçift yerine küme parantezlerinin kullanılmasıdır .
Brent Bradburn

4

Genellikle standart for döngüsünde küçük bir varyant kullanmayı severim. Bunu genellikle bir dizi uzak ana bilgisayarda bir komut çalıştırmak için kullanırım. Sayısal olmayan for-döngüler oluşturmama izin veren döngüler oluşturmak için bash'ın küme ayracı genişletmesinden yararlanıyorum.

Misal:

Uptime komutunu 1-5 ön uç ana bilgisayarlarında ve 1-3 arka uç ana bilgisayarlarında çalıştırmak istiyorum:

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

Bunu genellikle yukarıdaki daha okunaklı sürüm yerine satırların sonlarında noktalı virgül bulunan tek satırlı bir komut olarak çalıştırırım. Temel kullanım düşüncesi, kaşlı ayraçların bir dizeye eklenecek birden fazla değeri belirlemenize izin vermesidir (örn. Pre {foo, bar} post, prefoopost, prebarpost'ta) ve çift noktaları kullanarak sayma / dizilere izin vermesidir (bir. .z vb.) Bununla birlikte, çift dönem sözdizimi, bash 3.0'ın yeni bir özelliğidir; önceki sürümler bunu desteklemeyecektir.


Bununla ilgili olarak, ya $ host var bir kazayla boş bir satırsa? Yine de ssh ateşleyecekti. Peki bundan nasıl kaçınabilirim? Benim durumumda farklı bir şey yapıyorum ve bu yüzden cevabınız bana yardımcı olacak. Gmail'de yeni iletiler olup olmadığını kontrol etmeye çalışıyorum ve bulunursa, bir den ve konuya ait bir SMS gönderiyorum. Okumak isterseniz sorum "İki Bash Komutunu Bağlama" olarak etiketlendi.
Volomike

Boş bir $ host var alacağına inanmıyorum. Bunun nedeni, yukarıdaki örneğin küme ayracı genişletmesi kullanmasıdır. For döngüsü, $ host değişkenini açıkça şu değerlere ayarlar: frontend1.mycompany.com frontend2.mycompany.com. . backend1.mycompany.com Ancak bunun boş bir değere sahip olmasının bir yolunu görürseniz; Bilmek ilgimi çeker. Bir sorun olması durumunda, ssh'yi koşullu bir test içinde çalıştırabilirsiniz.
terson

1

sadece bash ile ilgileniyorsanız, yukarıda sunulan "for ((...))" çözümü en iyisidir, ancak tüm aygıtlarda çalışacak POSIX SH uyumlu bir şey istiyorsanız, "ifade" kullanmanız gerekir ve "while", çünkü "(())" veya "seq" veya "i = i + 1" çeşitli kabuklar arasında o kadar da taşınabilir değil


0

Dosyaları işlemek için her zaman bunun varyasyonlarını kullanıyorum ...

* .log dosyasındaki dosyalar için; do echo "Aşağıdakilerle şeyler yapın: $ files"; echo "Daha fazla şey yapın: $ files"; bitti;

İlgilendiğiniz şey dosya listelerini işlemekse , dosyalar için -execdir seçeneğine bakın .


Sanırım bulmak için -execdir seçeneğini kastediyorsunuz
sonraki duyuruya kadar duraklatıldı.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.