Döngüler için bash komut dosyası oluşturma. Bash Temelleri: Döngüler

Bash kabuğu, değer dizileri üzerinde yineleme yapmanıza olanak tanıyan for döngülerini destekler. Bu tür döngülerin temel yapısı şöyledir:

Listedeki var için komut tamamlandı
Döngünün her yinelemesinde listedeki bir sonraki değer var değişkenine yazılacaktır. Bu nedenle döngünün ilk geçişi listedeki ilk değeri kullanacaktır. İkincisinde - ikincisinde vb. - döngü son öğeye ulaşana kadar.

Basit değerler üzerinde yineleme

Belki de bash betiklerindeki for döngüsünün en basit örneği, basit değerler listesinin yinelenmesidir:

#!/bin/bash birinci ikinci üçüncü dördüncü beşincide var için echo do echo $var öğesi tamamlandı
Bu betiğin sonuçları aşağıda gösterilmiştir. $var değişkeninin listedeki öğeleri sıralı olarak içerdiğini açıkça görebilirsiniz. Bu, döngü sonuncusuna ulaşana kadar olur.


Döngü için basit

$var değişkeninin döngüden çıkarken değerini koruduğunu, içeriğinin değiştirilebileceğini ve genel olarak onunla diğer değişkenler gibi çalışabileceğinizi lütfen unutmayın.

Karmaşık değerler üzerinde yineleme

For döngüsünü başlatmak için kullanılan liste, yalnızca tek bir kelimeden oluşan basit dizeleri değil, aynı zamanda birden fazla kelime ve noktalama işareti içeren tüm ifadeleri de içerebilir. Örneğin, şöyle görünebilir:

#!/bin/bash for var in birinci "ikinci" "üçüncü" "Ben yapacağım" do echo "Bu: $var" bitti
Bu döngü listeden geçtikten sonra olan şey budur. Gördüğünüz gibi sonuç oldukça bekleniyor.


Karmaşık değerler üzerinde yineleme
TNW-CUS-FMP - hizmetlerimizde %10 indirim için promosyon kodu, 7 gün içinde etkinleştirilebilir"

Komutun sonuçlarından elde edilen bir listeyle döngünün başlatılması

For döngüsünü başlatmanın başka bir yolu da ona bir komutun sonucu olan bir liste iletmektir. Burada komut ikamesi bunları yürütmek ve çalışmalarının sonuçlarını elde etmek için kullanılır.

#!/bin/bash file="dosyam" for var in $(cat $file) do echo " $var" bitti
Bu örnek, bir dosyanın içeriğini okuyan cat komutunu kullanır. Ortaya çıkan değer listesi döngüye aktarılır ve ekranda görüntülenir. Erişmekte olduğumuz dosyanın yeni satırlarla ayrılmış bir sözcük listesi içerdiğini lütfen unutmayın; boşluk kullanılmaz.


Bir dosyanın içeriği arasında dolaşan bir döngü

Burada, eğer satır satır veri işleme bekleniyorsa, satırları boşluklarla ayrılmış birkaç kelime içerebilen daha karmaşık yapıya sahip bir dosya için böyle bir yaklaşımın işe yaramayacağını dikkate almalıyız. Döngü satırları değil tek tek kelimeleri işleyecektir.

Ya ihtiyacınız olan şey bu değilse?

Alan ayırıcılar

Yukarıdaki özelliğin nedeni, alan ayırıcılarını belirtmenize olanak tanıyan IFS (Dahili Alan Ayırıcı) adı verilen özel bir ortam değişkenidir. Varsayılan olarak bash kabuğu aşağıdaki karakterleri alan ayırıcıları olarak kabul eder:
  • Uzay
  • Sekme karakteri
  • Satır besleme karakteri
Bash veride bu karakterlerden herhangi biriyle karşılaşırsa listedeki bir sonraki bağımsız değerin ondan önce geldiğini varsayar.

Sorunu çözmek için IFS ortam değişkenini geçici olarak değiştirebilirsiniz. Alan ayırıcı olarak yalnızca yeni satıra ihtiyacınız olduğunu varsayarak bunu bir bash betiğinde nasıl yapacağınız aşağıda açıklanmıştır:

IFS=$"\n"
Bu komutu bash betiğinize eklediğinizde, beklendiği gibi çalışacak, boşlukları ve sekmeleri yok sayacak ve yalnızca yeni satır karakterlerini alan ayırıcı olarak değerlendirecektir.

#!/bin/bash file="/etc/passwd" IFS=$"\n" for var in $(cat $file) do echo " $var" bitti
Bu betik çalıştırılırsa, döngünün her yinelemesinde dosyaya yazılan bir sonraki satıra erişim sağlayarak kendisinden tam olarak ne isteniyorsa çıktısını verecektir.


For döngüsünde bir dosyanın satır satır geçişi

Ayırıcılar başka karakterler de olabilir. Örneğin yukarıda /etc/passwd dosyasının içeriğini görüntüledik. Satırlardaki kullanıcı verileri iki nokta üst üste ile ayrılır. Bu tür dizeleri bir döngüde işlemeniz gerekiyorsa, IFS şu şekilde yapılandırılabilir:

Bir dizinde bulunan dosyalar arasında geçiş yapma

Bash betiklerinde for döngülerinin en yaygın kullanımlarından biri, bir dizinde bulunan dosyaların arasında geçiş yapmak ve bu dosyaları işlemektir.

Örneğin, dosya ve klasörlerin nasıl listeleneceği aşağıda açıklanmıştır:

/home/likegeeks/* içindeki dosya için #!/bin/bash do if [ -d "$file" ] ardından echo "$file bir dizindir" elif [ -f "$file" ] ardından echo "$file bir dizindir dosya" fi bitti
Bu makale dizisini okuduysanız, if-then yapısının yapısını ve ayrıca bir dosyayı bir klasörden nasıl ayırt edeceğinizi anlamalısınız. Yukarıdaki kodu anlamakta zorlanıyorsanız bu materyali tekrar okuyun.

Komut dosyasının çıktısı budur.


Bir klasörün içeriğini görüntüleme

Döngüyü nasıl başlattığımıza, yani klasör adresinin sonundaki "*" joker karakterine dikkat edin. Bu sembol, "herhangi bir addaki tüm dosyalar" anlamına gelen bir joker karakter olarak düşünülebilir. desenle eşleşen dosya adlarının otomatik olarak değiştirilmesini düzenlemenize olanak tanır.

Bir if ifadesinde bir koşulu test ederken, değişken adını tırnak içine alırız. Bunun nedeni, dosya veya klasör adının boşluk içerebilmesidir.

Döngüler için C tarzı

C programlama diline aşina iseniz, döngüler için bash'ı tanımlamaya yönelik sözdizimi size tuhaf gelebilir, çünkü döngüleri bu şekilde tanımlamaya açıkça alışkınsınız:

(i = 0; ben için)< 10; i++) { printf("number is %d\n", i); }
Bash komut dosyalarında, bazı farklılıklar olmasına rağmen açıklaması C tarzı döngülere çok benzeyen for döngülerini kullanabilirsiniz. Bu yaklaşıma sahip döngü şeması şuna benzer:

For ((değişkenin başlangıç ​​değeri; döngünün bitiş koşulu; değişkenin değişimi))
Bash'ta şöyle yazılabilir:

İçin ((a = 1; a< 10; a++))
İşte çalışan bir örnek:

#!/bin/bash for ((i=1; i<= 10; i++)) do echo "number is $i" done
Bu kod 1'den 10'a kadar sayıların bir listesini verecektir.

C tarzında bir döngü çalıştırma

döngü sırasında

for yapısı, bash betiklerinde döngüleri organize etmenin tek yolu değildir. Burada while döngülerini de kullanabilirsiniz. Böyle bir döngüde, belirli bir koşulu kontrol etmek ve test edilen koşul sıfıra dönene kadar döngünün gövdesini yürütmek veya belirli bir işlemin başarılı bir şekilde tamamlanması için bir sinyal vermek için bir komut belirtebilirsiniz. Döngü koşulu sıfırdan farklı bir değer döndürdüğünde, yani hata anlamına geldiğinde döngü duracaktır.

İşte while döngülerinin organizasyonunun bir diyagramı
durum kontrol komutu sırasında
Yapmak
diğer takımlar
Tamamlandı

Bunun gibi bir döngüye sahip örnek bir komut dosyasına bakalım:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] bitti
Döngüye girişte $var1 değişkeninin sıfırdan büyük olup olmadığı kontrol edilir. Eğer öyleyse, döngünün gövdesi yürütülür ve burada değişkenin değerinden bir çıkarılır. Bu her yinelemede gerçekleşir ve değişkenin değerini değiştirilmeden önce konsola yazdırırız. $var1 0 değerine ulaştığında döngü durur.

while döngüsünün sonucu

$var1 değişkenini değiştirmezseniz bu, betiğin sonsuz bir döngüye girmesine neden olur.

İç içe geçmiş döngüler

Diğer döngüleri başlatmak dahil, döngünün gövdesindeki herhangi bir komutu kullanabilirsiniz. Bu tür yapılara iç içe döngüler denir:

#!/bin/bash for ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Bu betiğin çıktısını aşağıda bulabilirsiniz. Gördüğünüz gibi, önce dış döngünün ilk yinelemesi gerçekleştirilir, ardından iç döngünün üç yinelemesi gerçekleştirilir, tamamlandıktan sonra dış döngü tekrar devreye girer, ardından tekrar iç döngü devreye girer.

İç içe geçmiş döngüler

Dosya İçeriklerinin İşlenmesi

Çoğu zaman, dosyaları işlemek için iç içe döngüler kullanılır. Yani, dıştaki döngü dosyanın satırları üzerinde yineleniyor ve içteki döngü zaten her satırla çalışıyor. Örneğin, /etc/passwd dosyasının işlenmesi şöyle görünür:

#!/bin/bash IFS=$"\n" $(cat /etc/passwd) içindeki giriş için do echo "$entry içindeki değerler –" IFS=: $entry içindeki değer için do echo " $value" bitti Tamamlandı
Bu scriptte iki döngü var. İlki, sınırlayıcı olarak yeni satır karakterini kullanarak satırları geçer. Dahili olan, alanları iki nokta üst üste ile ayrılmış dizeleri ayrıştırmakla meşgul.

Dosya Veri İşleme

Bu yaklaşım, CSV dosyalarını veya benzer dosyaları işlerken, sınırlayıcı karakteri gerektiği gibi IFS ortam değişkenine yazarak kullanılabilir.

Döngü yönetimi

Belki döngüye girdikten sonra, döngü değişkeni, döngüyü sonlandırmak için başlangıçta belirtilen koşula karşılık gelmeyen belirli bir değere ulaştığında onu durdurmanız gerekecektir. Böyle bir durumda döngünün normal şekilde tamamlanmasını beklemek gerekecek mi? Elbette hayır ve bu gibi durumlarda aşağıdaki iki komut işinize yarayacaktır:
  • kırmak
  • devam etmek

mola komutu

Bu komut, bir döngünün yürütülmesini kesmenizi sağlar. Hem for hem de while döngüleri için kullanılabilir:

var1 için #!/bin/bash 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] sonra break fi echo "Numara: $var1" bitti
Normal koşullar altında böyle bir döngü, listedeki tüm değerler listesinin üzerinden geçecektir. Ancak bizim durumumuzda $var1 değişkeni 5'e eşit olduğunda yürütmesi kesintiye uğrayacaktır.

For döngüsünden erken çıkmak

İşte aynı şey, ancak while döngüsü için:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] ardından break fi echo "Yineleme: $var1" var1=$(($var1 + 1)) bitti
$var1 5'e ulaştığında yürütülen break komutu döngüyü keser. Konsol önceki örnektekiyle aynı şeyi gösterecektir.

devam komutu

Döngünün gövdesinde bu komutla karşılaşıldığında, döngüden çıkmadan mevcut yineleme erken biter ve bir sonraki yineleme başlar. Bir for döngüsündeki Continue komutuna bakalım:

#!/bin/bash for ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Döngü içindeki koşul sağlandığında, yani $var1 5'ten büyük ve 10'dan küçük olduğunda, kabuk devam komutunu yürütür. Bu, döngünün gövdesinde kalan komutların atlanması ve bir sonraki yinelemeye geçilmesiyle sonuçlanır.

For döngüsünde devam komutu

Döngüde Çalışan Çıkış İşleme

Bir döngüden gelen veri çıkışı, çıkışın yeniden yönlendirilmesi veya bir boru hattına geçirilmesi yoluyla işlenebilir. Bu, yapılan ifadeden sonra çıktı işleme komutları eklenerek yapılır.

Örneğin, çıktıyı bir döngüde ekranda göstermek yerine, hepsini bir dosyaya yazabilir veya başka bir yere iletebilirsiniz:

#!/bin/bash for ((a = 1; a< 10; a++)) do echo "Number is $a" done >dosyam.txt echo "tamamlandı."
Kabuk myfile.txt dosyasını oluşturacak ve for ifadesinin çıktısını bu dosyaya yönlendirecektir. Dosyayı açalım ve tam olarak beklediğimizi içerdiğinden emin olalım.

Döngü çıktısını dosyaya yönlendir

Örnek: Yürütülebilir dosyaları arama

Daha önce ele aldıklarımızı kullanalım ve faydalı bir şeyler yazalım. Örneğin sistemde hangi yürütülebilir dosyaların mevcut olduğunu bulmanız gerekiyorsa PATH ortam değişkeninde kayıtlı tüm klasörleri tarayabilirsiniz. Bunun için ihtiyacımız olan tüm araçlara zaten sahibiz, hepsini bir araya getirmemiz yeterli:

#!/bin/bash IFS=: $PATH içindeki klasör için echo "$klasör:" yapın $klasör/* içindeki dosya için yapın if [ -x $dosya ] ardından echo " $dosya" fi bitti
Küçük ve basit olan bu komut dosyası, PATH'den klasörlerde saklanan yürütülebilir dosyaların bir listesini almamıza olanak sağladı.

PATH değişkeninden klasörlerdeki yürütülebilir dosyaları arama

Sonuçlar

Bugün bash scriptlerindeki for ve while döngülerinden, nasıl çalıştırılacağından, nasıl yönetileceğinden bahsettik. Artık döngülerde farklı sınırlayıcılara sahip dizeleri nasıl işleyeceğinizi biliyorsunuz, döngülerdeki veri çıktısını dosyalara nasıl yönlendireceğinizi, dizinlerin içeriğini nasıl görüntüleyeceğinizi ve analiz edeceğinizi biliyorsunuz.

Yalnızca bu makale dizisinde ve bu ikincisinde belirtilenleri bilen bir bash betikleri geliştiricisi olduğunuzu varsayarsak, o zaman zaten yararlı bir şeyler yazabilirsiniz. Önümüzde, parametreleri ve komut satırı anahtarlarını bash betiklerine nasıl aktaracağınızı ve bunlarla ne yapacağınızı öğreneceğiniz üçüncü bölüm var.

Döngü türlerindeki farkın kısa bir açıklaması:

for - yürütülecek nesneler olduğu sürece bir eylem gerçekleştirecektir (örneğin, stdin'den bir akışı, bir dosyayı veya bir işlevi okumak);
while - eylemi gerçekleştirene kadar durum doğru;
kadar - yürütüleceği sürece durum gerçek olmayacak, yani şimdilik yalan.

Döngü için

Betiğin bu versiyonunu bir döngüyle ele alalım:

$ cat loop.sh #!/bin/bash 'ls -1' içindeki değişken için do echo "$değişken" tamamlandı

Sözdizimi çok basittir ve örnekte oldukça açık bir şekilde gösterilmiştir:

for (döngüyü başlat) değişkeni (üzerinde eylemler gerçekleştireceğimiz bir değişken bildirin) (döngüye bir akış gönder) 'ls -1' (yürütülecek ve $değişken değişkenine iletilecek komut). Yap ve bitti, alınan veriler üzerinde ana eylemlerin gerçekleştirileceği döngünün "gövdesi"dir ve echo "$değişken" döngü tarafından gerçekleştirilen gerçek eylemdir.

Şimdi örneği biraz değiştirelim ve komutu açıkça belirtmek yerine ikinci değişkeni kullanalım:

$ cat loop.sh #!/bin/bash ls=`ls -1` $ls'deki değişken için do echo "$variable" bitti

Artık ls -1 komutu ayrı bir değişkene aktarılıyor ve bu da döngüyle daha esnek çalışmanıza olanak tanıyor. Döngüdeki bir değişken yerine bir işlevi de kullanabilirsiniz:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) 'lsl'deki değişken için do echo "$değişken" bitti

For döngüsünün ana koşulu, kendisine iletilen komut eylem nesneleri içerdiği sürece yürütülecek olmasıdır. Yukarıdaki örneğe göre - ls -1'de görüntülenecek dosyalar olduğu sürece - döngü bunları bir değişkene iletecek ve "döngü gövdesini" çalıştıracaktır. Dizindeki dosyaların listesi biter bitmez döngü yürütülmesini tamamlayacaktır.

Örneği biraz daha karmaşık hale getirelim.

Dizin bir dosya listesi içerir:

$ ls -1 dosya1 dosya2 dosya3 dosya4 dosya5 döngü.sh nofile1 nofile2 nofile3 nofile4 nofile5

İçlerinden sadece "" kelimesi olmayanları seçmemiz gerekiyor. HAYIR«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` $lsl'deki değişken için do echo "$variable" | grep -v "hayır" yapıldı $ ./loop.sh dosya1 dosya2 dosya3 dosya4 dosya5 loop.sh

Ayrıca bir döngüde koşullu ifadeler de kullanabilirsiniz ( koşullu ifadeler) […] Koşulları kontrol etmek ve koşulun tetiklenmesi durumunda döngüyü kesmek için break deyimini kullanmak.

Bu örneği düşünün:

$ cat loop.sh #!/bin/bash lsl=`ls -1` $lsl'deki değişken için do if [ $variable != "loop.sh" ] ardından echo "$variable" | grep -v "hayır" else fi bitti

Döngü, loop.sh dosyasıyla karşılaşılıncaya kadar devam edecektir. Döngünün yürütülmesi bu dosyaya ulaşır ulaşmaz döngü break komutuyla kesilecektir:

$ ./loop.sh dosya1 dosya2 dosya3 dosya4 dosya5

Başka bir örnek, döngünün gövdesini çalıştırmadan hemen önce aritmetik işlemlerin kullanılmasıdır:

$ cat loop.sh #!/bin/bash for ((count=1; count<11; count++)) do echo "$count" done

Burada üç kontrol komutu belirledik - sayım=1, sayım 11'den küçükken bir kontrol koşulu ve yürütülecek komut - sayım +1:

WHILE ve UNTIL döngüleri

While döngüsünün nasıl çalıştığını açıkça gösteren basit bir örnek:

$ cat loop.sh #!/bin/bash count=0 while [ $count -lt 10 ] do ((count++)) echo $count bitti

$count değişkenini sıfıra ayarlıyoruz ve ardından "$count ondan küçükken döngüyü yürütün" koşuluyla while döngüsünü çalıştırıyoruz. Döngünün gövdesinde yürütüyoruz sonek artışı$count değişkenine +1 ve sonuç stdout'a yazdırılır.

Yürütme sonucu:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

$count değişkeninin değeri 10 olur olmaz döngü durduruldu.

while'ın nasıl çalıştığını gösteren "sonsuz" döngüye güzel bir örnek:

$ cat loop.sh #!/bin/bash count=10 while [ 1 = 1 ] do ((count++)) echo $count bitti $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C

Until döngüsü de benzer şekilde çalışır ancak ters yönde çalışır:

$ cat loop.sh #!/bin/bash count=0 ta ki [ $count -gt 10 ] do ((count++)) echo $count tamamlanana kadar

Burada da benzer bir koşul koyuyoruz ama “değişken 10’dan küçükken” yerine “değişken 10’dan büyük oluncaya kadar” ifadesini koyuyoruz. Yürütme sonucu:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

Yukarıdaki "sonsuz döngü" örneği, Until kullanılarak yürütülürse, while'dan farklı olarak hiçbir çıktı vermez:

$ cat loop.sh #!/bin/bash count=10 ta ki [ 1 = 1 ] do ((count++)) echo $count bitti $ ./loop.sh $

Çünkü " durum"aslında" doğru"—döngünün gövdesi yürütülmeyecek.

Tıpkı for döngüsünde olduğu gibi while ve Until fonksiyonları da kullanılabilir. Örneğin, sunucu durumunu kontrol eden gerçek hayattaki bir komut dosyasından bir döngü Erkek kedi(PID sistemden alınır SLES, diğer sistemlerde farklılık gösterebilir), biraz basitleştirilmiş bir versiyon:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep Tomcat | grep -v grep | grep Java | awk "(print $2)"` ) while check_tomcat_status do if [ -n "$ RUN" ] sonra printf "UYARI: Tomcat hala PID $RUN ile çalışıyor." else printf "Tomcat durdu, devam ediyor...nn" break fi bitti

Yürütme sonucu:

$ ./loop.sh UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala çalışıyor PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 26548 ile çalışıyor.UYARI: Tomcat hala PID 14435 ile çalışıyor

Tam versiyon:

Check_tomcat_status () ( RUN=`ps aux | grep Tomcat | grep -v grep | grep java | awk "(yazdır $2)"` ) while check_tomcat_status; do if [ -n "$RUN" ] ardından printf "UYARI: Tomcat hala PID $RUN ile çalışıyor. Durdurulsun mu?" yanıtla "Tomcat durduruluyor..." "Kurulum devam ediyor..." && $CATALINA_HOME/bin/shutdown . sh 2&>1 /dev/null || uyku 2'yi kes if [ -n "$RUN" ] sonra printf "Tomcat hala çalışıyor. Öldürülsün mü?" cevap "Tomcat öldürülüyor..." "Kurulum devam ediyor...n" && kill $RUN || uykuyu kes 2 fi else printf "Tomcat durdu, devam ediyor...nn" mola fi bitti

Yanıt işlevi makalede açıklanmıştır, ancak burada biraz geliştirilmiş bir sürüm kullanılmıştır:

Yanıt () ( yanıt okunurken; echo case $yanıtı yapın |) printf "$1n" return 0 break ;; |) printf "$2n" dönüş 1 ara ;; *) printf "Lütfen E(evet) veya H(hayır) girin!" esac bitti )

Burada hem while hem de Until kullanmak mümkündü, ancak for döngüsü mümkün değildi, çünkü for bir kez işe yarayacaktı (PID'yi aldı ve sona erdi).

için VAR içinde 1 2 3...K Yapmak Tamamlandı veya bir satırda: için VAR içinde 1 2 3...K; Yapmak ; Tamamlandı
Değişkene hem sayısal değerleri hem de ASCII karakterlerini koymak mümkündür.
Örnek: $ i için 1 2 A B Abc ; echo $i yapın; yapıldı 1 2 A B Abc Video kod dönüştürme için bir değişkendeki dosyaların "maske" ile listelenmesine örnek: için Ben içinde*.avi; Yapmak ; Tamamlandı

2. Başka bir komutun sonuçlarını değiştirmek

için VAR içinde $(); Yapmak ; Tamamlandı
seq komutunun sonuçlarının kullanımına bir örnek: için Ben içinde$(seq [ANAHTAR]); Yapmak yankı $i; Tamamlandı$ i için $(sıra 3); echo $i yapın; $(sıra 3 5) cinsinden i için 1 2 3 $ yapıldı; echo $i yapın; $'da i için 3 4 5 $ yapıldı(sıra 2 2 6); echo $i yapın; tamamlandı 2 4 6 ls komutunun sonuçlarının kullanımına bir örnek: $ for i in $(ls /$HOME/Video); echo $i yapın; yapıldı 001.avi 002.avi 003.avi

3. C tarzı (C tarzı) kullanarak oyuncu değişikliği

için((EXPR1; EXPR2; EXPR3)) Yapmak <список команд> Tamamlandı için((i=1; ben<=3 ; i++)); Yapmak yankı $i; Tamamlandı$ için ((i=1; i<=3 ; i++)); do echo $i; done 1 2 3 Подробнее о применении C-style в Bash

4. Kıvrımlı parantez kullanarak numaralandırma (..)

(START..END) sözdizimi bash sürüm 3.0+ ile başlayarak desteklenir ve (START..END..INCREMENT) sözdizimi bash sürüm 4.0+ ile başlayarak desteklenir:

için VAR içinde {..} Yapmak Tamamlandı veya için VAR içinde {....} Yapmak TamamlandıÖrnekler: (1..3)'te i için $; echo $i yapın; (4..8..2)'de i için 1 2 3 veya $ yapıldı; echo $i yapın; yapıldı 4 6 8 Değerlerin hem arttırılması hem de azaltılması için sayma mümkündür: $ i için (6..-4..3); echo $i yapın; yapıldı 6 3 0 -3

5. Parametre değişikliği ( içinde "$@")

Betiğe aktarılan her parametre için komutları yürütür. için VAR içinde $@ Yapmak Tamamlandı veya bir satırda: için VAR içinde $@; Yapmak ; Tamamlandı
Yani bir test.sh betiği oluşturursanız #!/bin/sh için VAR içinde $@ Yapmak Eko$VAR Tamamlandı daha sonra onu parametrelerle çalıştırdığınızda: $ ./test.sh param1 param2 param3 param1 param2 param3 Part içinde$@ atlanabilir. Daha sonra test.sh betiği yeniden yazılacaktır: #!/bin/sh için VAR Yapmak Eko$VAR Tamamlandı
Size birkaç örnek vereyim (ile içinde ve olmadan): $ function FUNC_1 ( $@ içindeki VAR için; do echo $VAR; yapıldı; ) $ FUNC_1 param1 param2 param3 param1 param2 param3 $ function FUNC_2 ( VAR için; do echo $VAR; yapıldı; ) $ FUNC_2 param1 param2 param3 param1 param2 param3

6. for döngüsünde Continue ve Break'in kullanılması

Yukarıdaki yapıların tümü için, döngünün bir sonraki elemanına geçmek için "devam et" veya döngüden çıkmak için "break" komutlarını kullanmak mümkündür.

Örnek (i=6 olduğunda tamamlayın ve i=3 ve i=5 olduğunda yürütmeyin): için(1..8)'de i; Yapmak eğer[ $i -eq 6 ]; Daha sonra kırmak; fi eğer[ $i -eq 3 ] || [ $i -eq 5 ]; Daha sonra devam etmek; fi yankı $i Tamamlandı Yürütme sonucu: $ $ i için (1..8); do \ > if [ $i -eq 6 ]; sonra kır; fi; \ > if [ $i -eq 3 ] || [ $i -eq 5 ]; sonra devam edin; fi; \ > echo $i; \ > tamamlandı 1 2 4

Dikkat: Gönderide gizli faydalar var!

döngüler için

Bash kabuğu, değer dizileri üzerinde yineleme yapmanıza olanak tanıyan for döngülerini destekler. Bu tür döngülerin temel yapısı şöyledir:

Listedeki var için komut tamamlandı

Döngünün her yinelemesinde listedeki bir sonraki değer var değişkenine yazılacaktır. Bu nedenle döngünün ilk geçişi listedeki ilk değeri kullanacaktır. İkincisinde - ikincisinde vb. - döngü son öğeye ulaşana kadar.

Basit değerler üzerinde yineleme

Belki de bash betiklerindeki for döngüsünün en basit örneği, basit değerler listesinin yinelenmesidir:

#!/bin/bash birinci ikinci üçüncü dördüncü beşincide var için echo do echo $var öğesi tamamlandı

Bu betiğin sonuçları aşağıda gösterilmiştir. $var değişkeninin sırayla listedeki öğeleri içerdiğini açıkça görebilirsiniz. Bu, döngü sonuncusuna ulaşana kadar olur.



Döngü için basit

$var değişkeninin döngüden çıkarken değerini koruduğunu, içeriğinin değiştirilebileceğini ve genel olarak onunla diğer değişkenler gibi çalışabileceğinizi lütfen unutmayın.

Karmaşık değerler üzerinde yineleme

For döngüsünü başlatmak için kullanılan liste, yalnızca tek bir kelimeden oluşan basit dizeleri değil, aynı zamanda birden fazla kelime ve noktalama işareti içeren tüm ifadeleri de içerebilir. Örneğin, hepsi şöyle görünebilir:

#!/bin/bash for var in birinci "ikinci" "üçüncü" "Ben yapacağım" do echo "Bu: $var" bitti

Bu döngü listeden geçtikten sonra olan şey budur. Gördüğünüz gibi sonuç oldukça bekleniyor.



Karmaşık değerler üzerinde yineleme
TNW-CUS-FMP - hizmetlerimizde %10 indirim için promosyon kodu, 7 gün içinde etkinleştirilebilir"

Komutun sonuçlarından elde edilen bir listeyle döngünün başlatılması

For döngüsünü başlatmanın başka bir yolu da ona bir komutun sonucu olan bir liste iletmektir. Burada komutların değiştirilmesi, bunları yürütmek ve çalışmalarının sonuçlarını elde etmek için kullanılır.

#!/bin/bash file="dosyam" for var in $(cat $file) do echo " $var" bitti

Bu örnek, bir dosyanın içeriğini okuyan cat komutunu kullanır. Ortaya çıkan değer listesi döngüye aktarılır ve ekranda görüntülenir. Erişmekte olduğumuz dosyanın yeni satırlarla ayrılmış bir sözcük listesi içerdiğini lütfen unutmayın; boşluk kullanılmaz.



Bir dosyanın içeriği arasında dolaşan bir döngü

Burada, eğer satır satır veri işleme bekleniyorsa, satırları boşluklarla ayrılmış birkaç kelime içerebilen daha karmaşık yapıya sahip bir dosya için böyle bir yaklaşımın işe yaramayacağını dikkate almalıyız. Döngü satırları değil tek tek kelimeleri işleyecektir.

Ya ihtiyacınız olan şey bu değilse?

Alan ayırıcılar

Yukarıdaki özelliğin nedeni, alan ayırıcılarını belirtmenize olanak tanıyan IFS (Dahili Alan Ayırıcı) adı verilen özel bir ortam değişkenidir. Varsayılan olarak bash kabuğu aşağıdaki karakterleri alan ayırıcıları olarak kabul eder:

  • Uzay
  • Sekme karakteri
  • Satır besleme karakteri

Bash veride bu karakterlerden herhangi biriyle karşılaşırsa listedeki bir sonraki bağımsız değerin ondan önce geldiğini varsayar.

Sorunu çözmek için IFS ortam değişkenini geçici olarak değiştirebilirsiniz. Alan ayırıcı olarak yalnızca yeni satıra ihtiyacınız olduğunu varsayarak bunu bir bash betiğinde nasıl yapacağınız aşağıda açıklanmıştır:

IFS=$"n"

Bu komutu bash betiğinize eklediğinizde, beklendiği gibi çalışacak, boşlukları ve sekmeleri yok sayacak ve yalnızca yeni satır karakterlerini alan ayırıcı olarak değerlendirecektir.

#!/bin/bash file="/etc/passwd" IFS=$"n" for var in $(cat $file) do echo " $var" bitti

Bu betik çalıştırılırsa, döngünün her yinelemesinde dosyaya yazılan bir sonraki satıra erişim sağlayarak kendisinden tam olarak ne isteniyorsa çıktısını verecektir.



For döngüsünde bir dosyanın satır satır geçişi

Ayırıcılar başka karakterler de olabilir. Örneğin yukarıda /etc/passwd dosyasının içeriğini görüntüledik. Satırlardaki kullanıcı verileri iki nokta üst üste ile ayrılır. Bu tür dizeleri bir döngüde işlemeniz gerekiyorsa, IFS şu şekilde yapılandırılabilir:

Bir dizinde bulunan dosyalar arasında geçiş yapma

Bash betiklerinde for döngülerinin en yaygın kullanımlarından biri, bir dizinde bulunan dosyaların arasında geçiş yapmak ve bu dosyaları işlemektir.

Örneğin, dosya ve klasörlerin nasıl listeleneceği aşağıda açıklanmıştır:

/home/likegeeks/* içindeki dosya için #!/bin/bash do if [ -d "$file" ] ardından echo "$file bir dizindir" elif [ -f "$file" ] ardından echo "$file bir dizindir dosya" fi bitti

5

Komut dosyanız tehlikeli bir şekilde kodlanmış.

İlk olarak, "/bash" ve "/for" ile işaretlediğiniz için Bash kabuğunu kullandığınızı varsayıyorum.

Cevabımda, muhtemelen Bash'i öğrenmek için en iyi kaynak olan bu mükemmel Bash rehberinden alıntı yapacağım.

1) Hiçbir zaman Komut Değiştirmeyi kullanmayın, çünkü veya nazik, tırnak işaretleri olmadan. Burada büyük bir sorun var: Çıktıyı argümanlara bölmek için alıntılanmamış bir uzantı kullanmak.

Spesifik olarak konuşursak, $(find$ DIRWORK -type d -name work) ve $(find$ DIR -type f) Kelime Bölme işlemine tabi tutulacaktır; dolayısıyla, find adında boşluk bulunan bir dosya bulursa, yani "dosya adı", kelime bölme sonucu Bash, yinelenmesi için for komutuna 2 argüman iletecektir, yani biri "dosya" için, diğeri "isim" için. Bu durumda, eğer gerçekten varlarsa onlara zarar verme potansiyelinden ziyade, "dosya: böyle bir dosya veya dizin yok" ve "ad: böyle bir dosya veya dizin yok" ifadesini almanızı ummak istersiniz.

2) Anlaşmaya göre Ortam Değişkenleri(PATH, EDITOR, SHELL, ...) ve dahili kabuk değişkenleri (BASH_VERSION, RANDOM, ...) tamamen büyük harfle yazılmıştır. Diğer tüm değişken adları küçük harf olmalıdır. Değişken adları büyük/küçük harfe duyarlı olduğundan, bu kural çevresel ve dahili değişkenlerin yanlışlıkla geçersiz kılınmasını önler.

Bu, komut dosyanızın daha güvenli bir sürümüdür; bunun yerine onu kullanmanızı öneririm:

My_home = "/root/mydir" my_dir = $my_home/var" dir_work = "$ my_home/Local" while IFS= read -r -d "" f; do # Sanırım stderr'i de göz ardı etmek istiyorsunuz; # 2>&1'in geldiği yer burasıdır. if lsof -n " ​​$f" | grep "" > /dev/null 2> sonra echo "hey , ben "Artık daha güvendeyim!" bitti< <(find "$ dir_work" -type f -print0) while IFS= read -r -d "" f; do echo "2" done < <(find "$dir_work" -type d -name "work" -print0)

Gördüğünüz gibi IFS değişkeni boş olarak ayarlanmıştır, böylece okumanın satırın ön ve arka alanını kesmesi engellenir. Okuma komutu, a\0'a ulaşana kadar okumak için sınırlayıcı olarak boş satırı (-d "") kullanır. Bulmak buna göre m olmalıdır, bu nedenle verilerini yeni satır yerine \0 ile sınırlamak için -print0 seçeneğini kullanır. şaşırtıcı ve kötü niyetli bir şekilde dosya adının bir parçası olabilir. Böyle bir \n dosyasını iki parçaya bölmek kodumuzu bozacaktır.

Bulduğu belirtilen önceki yanıt... | isim okunurken; Yapmak...; find'ın çıktısını okumak için Done kullanılmalıdır, çıktı da kötü olabilir. While döngüsü, üst öğesinden kopyalanan değişkenlerin kendi kopyasıyla yeni bir alt kabukta çalışır. Bu kopya daha sonra ne istersen kullanılır. While döngüsü tamamlandığında, alt kabuk kopyası atılacak ve ebeveynin orijinal değişkenleri değiştirilmeyecektir.

Bu while döngüsü içindeki bazı değişkenleri değiştirip bunları daha sonra ana döngüde kullanmayı düşünüyorsanız, veri kaybını önleyecek daha güvenli bir komut dosyası kullanmayı düşünün.

0

"Hiçbir zaman Komut Değiştirmeyi tırnak işareti olmadan kullanmayın." Bu sadece bir ayrıntıdır, ancak bir değişken ayarladığınızda tırnak işaretleri olmadan komut değiştirmeyi kullanmak mümkündür: "bir şey = $(basename" boşluklu dosya adı ")". - Smith John 22 Nisan 13 2013-04-22 21:43:10

2

i için $(find$ DIRWORK -type d -name work); "2" yankısını yap bitti

bu satırı ilk uygulayan kişi olacak

$DIRWORK -type d -name çalışmasını bulun

find işleminin tamamlanmasını bekleyin ve ardından bir gün izin alıp tekrar for döngüsüne koyun

Find çıktısında i için; "2" yankısını yap bitti

ancak o zaman for döngüsü çalışmaya başlayacaktır.

Bu nedenle, eğer find'ın for döngüsünü bitirmesi uzun zaman alıyorsa, başlayabilmesi için uzun bir süre beklemesi gerekir.

Geçici bulma komutlarını etkileşimli olarak deneyin

$ zaman $DIRWORK'ü bul -type d -name işi

ve ne kadar süreceğini görün.

Ayrıca şunu unutmayın: dosya adları üzerinde yineleme yapmak için for döngüsü kullanmamalısınız. Şunun gibi okumayla bir while döngüsü kullanın:

Find$ DIRWORK -type d -isim çalışması | isim okunurken; "2" yankısını yap bitti

Bonus: find ile paralel olarak bir while döngüsü çalıştırır. Bu, find bir satır yazdırır yazdırmaz while döngüsünün bir yinelemeyi tamamlayacağı anlamına gelir. Find işleminin tamamlanmasını beklemeye gerek yoktur.