Bash while döngüsüne girdiyi yönlendirme ve döngü bittikten sonra değişkenleri koruma


88

Bash şunları kullanmanıza izin verir: cat <(echo "$FILECONTENT")

Bash ayrıca aşağıdakilerin kullanımına izin verir: while read i; do echo $i; done </etc/passwd

önceki ikisini birleştirmek için bu kullanılabilir: echo $FILECONTENT | while read i; do echo $i; done

Sonuncusundaki sorun, alt kabuk oluşturması ve while döngüsü bittikten sonra değişkene iartık erişilememesidir.

Sorum şu:

Böyle bir şeye nasıl ulaşılır: while read i; do echo $i; done <(echo "$FILECONTENT")veya başka bir deyişle: iDöngü halindeyken hayatta kaldığından nasıl emin olabilirim ?

Lütfen while ifadesini içine aldığımın farkında olduğumu {}ancak bunun sorunu çözmediğini unutmayın (işlevde while döngüsünü ve dönüş ideğişkenini kullanmak istediğinizi düşünün )



İlgili: stackoverflow.com/questions/37229058/… . Aşağıda belirtilen süreç ikamesi dahil tüm seçenekleri lastpipeve bunların artılarını ve eksilerini açıklar .
ivan_pozdeev

Yanıtlar:


117

İşlem Değiştirme için doğru gösterim şöyledir:

while read i; do echo $i; done < <(echo "$FILECONTENT")

iDöngüde atanan son değer daha sonra döngü sona erdiğinde kullanılabilir. Bir alternatif şudur:

echo $FILECONTENT | 
{
while read i; do echo $i; done
...do other things using $i here...
}

Küme parantezleri bir G / Ç gruplama işlemidir ve kendileri bir alt kabuk oluşturmazlar. Bu bağlamda, bir boru hattının bir parçasıdır ve bu nedenle bir kabuktaki olarak işletilmektedir, ama bunun nedeni biridir |, değil { ... }. Soruda bundan bahsediyorsun. AFAIK, bunların içinden bir işlevin içinden bir dönüş yapabilirsiniz.


Bash ayrıca shoptyerleşik sağlar ve birçok seçeneğinden biri şudur:

lastpipe

Ayarlanırsa ve iş kontrolü etkin değilse, kabuk geçerli kabuk ortamında arka planda yürütülmeyen bir ardışık düzenin son komutunu çalıştırır.

Böylece, bir komut dosyasında buna benzer bir şey kullanmak , değiştirileni döngüden sumsonra kullanılabilir hale getirir :

FILECONTENT="12 Name
13 Number
14 Information"
shopt -s lastpipe   # Comment this out to see the alternative behaviour
sum=0
echo "$FILECONTENT" |
while read number name; do ((sum+=$number)); done
echo $sum

Bunu komut satırında yapmak genellikle 'iş kontrolü etkin değil' hatası verir (yani komut satırında, iş kontrolü etkindir). Bunu bir komut dosyası kullanmadan test etmek başarısız oldu.

Tarafından da belirtildiği gibi, Gareth Rees yaptığı içinde cevap , bazen kullanabilirsiniz burada dize :

while read i; do echo $i; done <<< "$FILECONTENT"

Bu gerektirmez shopt; onu kullanarak bir işlemi kaydedebilirsiniz.


Cehaletimi bağışlayın. Bunun doğru çözüm olduğunu biliyorum ve yanıt olarak işaretledim, bu yüzden benim için çalıştı. Ama şimdi while read i; do echo $i; done < <(cat /etc/passwd); echo $ikoştuğumda iki kez son satıra dönmedi. Neyi yanlış yapıyorum?
Wakan Tanka

@WakanTanka: Biraz denemek zorunda kaldım ... Cevabın, başarısız okumanın sıfırlanacağına inanıyorum i, bu yüzden döngüden sonraki yankı boş bir satırı yankıladı.
Jonathan Leffler

1
Süreç Değiştirme referansı için tebrikler. Farkında değildim.
Atcold

@Wakan Tanka: Seninki ile aynı sonucu aldım, while read i; do x=$i; done < <(cat /etc/passwd); echo i=$i; echo x=$xçalıştım, // belki o günlerde bash davranışı değişti?
yurenchen

Sen bir hayat kurtarıcısın! Benzer bir çözüm için saatlerdir arıyordum. Seninki işe yarayan tek kişi.
Patenti


0

Bu işlev jpg dosyalarının $ NUM kez çoğaltılmasını sağlar (bash)

function makeDups() {
NUM=$1
echo "Making $1 duplicates for $(ls -1 *.jpg|wc -l) files"
ls -1 *.jpg|sort|while read f
do
  COUNT=0
  while [ "$COUNT" -le "$NUM" ]
  do
    cp $f ${f//sm/${COUNT}sm}
    ((COUNT++))
  done
done
}
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.