bash'ta, bir boru değerleri ayarladıktan sonra okuyun


22

Düzenleme: orijinal başlık "okuma bash'ta başarısız oldu"

Ksh ile değerleri ayırmak için uygun bir yol olarak read kullanıyorum:

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 
2 1
$

Ama bashta başarısız oluyor:

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 

$

Man sayfasında neden başarısız olduğuna dair bir neden bulamadım, herhangi bir fikir?


2
Bu, Greg'in Bash SSS sayfasının 024. sayfasında tartışılmaktadır (biraz belirsiz) .
Scott

Yanıtlar:


27

bash bir alt çizgi bağlamında bir boru hattının sağ tarafını çalıştırır , bu nedenle değişkenlerdeki değişiklikler (yani ne readolduğu) korunmaz - komutun sonunda alt kabuk yaptığında ölürler.

Bunun yerine, işlem ikamesini kullanabilirsiniz :

$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1

Bu durumda, readbirincil kabuğumuzda çalışır ve çıktı üreten komutumuz alt kabukta çalışır. <(...)Sözdizimi oluşturur bir altkabuk ve biz girişine yönlendirmek boru, onun çıkışını bağlayan readsıradan olan <operasyon . Çünkü readana kabuğunda değişkenler doğru ayarlanmış koştu.

Bir yorumda belirtildiği gibi, hedefiniz tam anlamıyla bir dizeyi bir şekilde değişkenlere bölmekse, burada dizeyi kullanabilirsiniz :

read a b dump <<<"1 2 3 4 5"

Sanırım bundan daha fazlası var, ama yoksa daha iyi bir seçenek.


3
Hatta read a b dump <<< '1 2 3 4 5'.
choroba

Herkese teşekkürler, btw mksh (cygwin'de) bash ile aynı şeyi yaptığını kaydettim.
Emmanuel

@Michael Homer İyi açıklama! Ben boru hattında her komut kendi alt kabukta çalıştırmanızı açıklayabilir başka bir örneği bulundu: cat /etc/passwd | (read -r line ; echo $line). Ama ertesi echoait $linedeğeri sadece parantezler (alt kabuğa) arasında var olması ve bu alanın, ekranda boru hattı koymak hiçbir şey değildir. Umut, birine yardım eder.
Yurij Goncharuk

17

Bu, hem gözlemlere hem de davranışlara izin verdiği için bir bashhata değildir ve gözlemlediğiniz talihsiz tutarsızlığa yol açar.POSIXbashksh

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12

Ek olarak, çok komutlu bir boru hattının her komutu bir alt kabuk ortamındadır; bununla birlikte, bir boru hattındaki komutların herhangi biri veya tümü geçerli ortamda yürütülebilir. Diğer tüm komutlar geçerli kabuk ortamında yürütülür.

Ancak bash 4.2ve daha yenisi ile, lastpipebeklenen sonucu elde etmek için etkileşimli olmayan komut dosyalarında seçeneği ayarlayabilirsiniz , örneğin:

#!/bin/bash

echo 1 2 3 4 5 | read a b dump
echo before: $b $a 
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a 

Çıktı:

before:
after: 2 1

1
+1 "lastpipe" bilgisi için teşekkür ederim. gecikme için özür dilerim
Emmanuel

1
sorun lastpipediğer kabuklarda (örneğin çizgi) çalışmaz olmasıdır. temelde bu taşınabilir alt kabukta her şeyi çalıştırmak için kısa bir yol yoktur, bkz. stackoverflow.com/questions/36268479/…
anarcat

1
@anarcat Bu doğru ama burada sorulan soru bash hakkındaydı.
jlliagre

@anarcat: POSIX'i başka bir nedenden ötürü değiştirmek istediğinden (PIPE Durumu) buraya bakın: unix.stackexchange.com/questions/476834/… Diğer mermileri değiştirmek önemsiz değil, birkaç ay sürdü Modern ksh'ın daha hızlı davranışını uygulamak için ayrıştırıcıyı ve yorumlayıcıyı Bourne Kabuğu (bosh) üzerine yeniden yazmak.
schily
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.