Kabuk komut dosyası giriş yönlendirme garipliğiyiz

oy
16

Herkes bu davranış açıklayabilir misiniz? Koşu:

#!/bin/sh
echo hello world | read var1 var2
echo $var1
echo $var2

hiçbir şey çıkmasına neden olur; çıktıya olma:

#!/bin/sh
echo hello world > test.file
read var1 var2 < test.file
echo $var1
echo $var2

beklenen çıktıyı üretir:

hello
world

test.file yapılacak yönlendirme İkinci örnekte yaptıklarını boru tek adımda yapmak gerekmez mi? Hem tire ve bash kabuğu ile aynı kod çalıştı ve her ikisi de aynı davranışı var.

Oluştur 05/08/2008 saat 20:26
kaynak kullanıcı
Diğer dillerde...                            


9 cevaplar

oy
11
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2

boru hatları bir kabuktaki içinde kendi bileşenlerinin her koşmak çünkü hiçbir çıktı üretir. Altkabuklarda kopyalarını miras yerine bunları paylaşmak yerine, ana kabuğun değişkenlerinin. Bunu dene:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
(
    echo $foo
    foo="foo contents modified"
    echo $foo
)
echo $foo

Parantez bir kabuktaki koþulur kod bölgesini tanımlamak ve $ foo içlerinde modifiye edildikten sonra orijinal değerini korur.

Şimdi bu deneyin:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
{
    echo $foo
    foo="foo contents modified"
    echo $foo
}
echo $foo

parantez tamamen gruplama için, hiçbir altkabuk oluşturulur, ve parantez içindeki modifiye $ foo onlara dışında değiştirilmiş aynı $ foo'dur.

Şimdi bu deneyin:

#!/bin/sh
echo "hello world" | {
    read var1 var2
    echo $var1
    echo $var2
}
echo $var1
echo $var2

Parantez içinde, yerleşik okuma düzgün $ var1 ve $ var2 oluşturur ve onlar yankılandı olsun görebilirsiniz. Parantezler dışında, onlar artık yok. Parantez içindeki tüm kod bir kabuktaki çalıştırıldıktan bir boru hattının bir bileşeni olduğu için .

Sen parantezler arasındaki kod keyfi miktarda koyabilirsiniz, bu nedenle başka bir şeyin çıkışını ayrıştırır kabuk bloğunu çalıştırmak için gerektiğinde bu boru-içine-a-blok inşaatı kullanabilirsiniz.

Cevap 19/09/2008 saat 03:20
kaynak kullanıcı

oy
9

Bu zaten doğru yanıtlandı, ama çözüm henüz ifade edilmemiştir. ksh kullanın bash değil. Karşılaştırmak:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | bash -s

Kime:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | ksh -s
hello
world

Ksh çünkü bu gibi küçük incelikler üstün bir programlama kabuktur. (Bash daha etkileşimli kabuk bence budur.)

Cevap 15/08/2008 saat 16:52
kaynak kullanıcı

oy
8

Yeni katılan bashbir lastpipeiş denetimi devre dışı bırakıldığında, cari kabuk değil, bir alt kabuk içinde çalıştırmak için bir boru hattı geçen komutu verir seçeneği.

#!/bin/bash
set +m      # Deactiveate job control
shopt -s lastpipe
echo "hello world" | read var1 var2
echo $var1
echo $var2

olacak aslında çıkış

hello
world
Cevap 26/07/2012 saat 13:10
kaynak kullanıcı

oy
8
read var1 var2 < <(echo "hello world")
Cevap 17/09/2008 saat 01:17
kaynak kullanıcı

oy
5

Pekala, ben bunu anladım!

Bu yakalamak için zor hata olduğunu, ancak yolu borular sonuçları kabuk tarafından işlenir. Bir boru hattının her unsuru ayrı bir işlemde çalışır. Okuma komutu setleri var1 ve var2 zaman onlara kendi altkabuk ekleyin, üst kabuk olarak belirlemesidir. altkabuk çıkışlar, var1 ve var2 değerleri kaybolur Yani zaman. Ancak, yapıyor deneyebilirsiniz

var1=$(echo "Hello")
echo var1

hangi beklenen cevabı verir. Maalesef tek değişkenler için bu sadece çalışır, bir anda birçok belirleyemezsiniz. Bir seferde birden çok değişkeni ayarlamak için tek bir değişkene okumalı ya ve çok değişkenli içine doğramak veya böyle bir şey kullanın:

set -- $(echo "Hello World")
var1="$1" var2="$2"
echo $var1
echo $var2

Bunun bir boru kullanmak kadar zarif değil itiraf ederken, işe yarıyor. Tabii ki değişkenlere dosyalarını okuma gerekiyordu okumak akılda tutmak, bu yüzden biraz daha zor olmalı standart girdiden okunur hale olmalıdır.

Cevap 05/08/2008 saat 21:09
kaynak kullanıcı

oy
4

(Bash kullanarak) bu konuda almak benim:

read var1 var2 <<< "hello world"
echo $var1 $var2
Cevap 04/03/2009 saat 10:52
kaynak kullanıcı

oy
4

yayını düzgün yanıtlandı ama belki bazı kullanım olabileceğini alternatif bir astar sunmak istiyorum.

yankı uzay ayrılmış değerler atayarak (ya da bu konuda stdout) değişkenleri kabuk için, kabuk dizileri kullanarak düşünebiliriz:

$ var=( $( echo 'hello world' ) )
$ echo ${var[0]}
hello
$ echo ${var[1]}
world

Bu örnek var ise, bir dizi ve içindekiler dizin dizi indeksi (0 ile başlar) olan yapı $ {var [göstergesi]} kullanılarak erişilebilir.

alakalı dizi indeksi atanan istediğiniz şekilde Böylece kadar çok sayıda parametre olabilir.

Cevap 14/09/2008 saat 18:00
kaynak kullanıcı

oy
4

boru versiyonu daha sonra zaman altkabuk çıkar yok edilir, yerel uzaya değişkeni okuyan bir altkabuk oluşturma da ondan.

Bu komutu yürütün

$ echo $$;cat | read a
10637

ve çalışan süreçleri bakmak için Pstree -p kullanmak, fazladan bir kabuk ana kabuğun asılı göreceksiniz.

    |                       |-bash(10637)-+-bash(10786)
    |                       |             `-cat(10785)
Cevap 05/08/2008 saat 21:00
kaynak kullanıcı

oy
3

Deneyin:

echo "hello world" | (read var1 var2 ; echo $var1 ; echo $var2 )

Sorun, birden fazla kişi belirttiğimiz gibi, bu var1 ve var2 zaman o altkabuk çıkışları tahrip edilen bir altkabuk ortamında oluşturulur olduğunu. Sonuç dek altkabuk tahrip yukarıdaki önler echo'd edilmiştir. Başka bir çözüm:

result=`echo "hello world"`
read var1 var2 <<EOF
$result
EOF
echo $var1
echo $var2
Cevap 17/09/2008 saat 03:15
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more