Bazı insanlar, read
bir satırı okuma komutunun hatalı olduğu fikrine sahiptir . Değil.
read
sözcükleri$IFS
sınırlandırılmış ve sınırlayıcılardan kaçmak için (ya da satırları devam ettirmek için) ters eğik çizgi kullanılabilecek olan (muhtemelen ters eğik çizgi ile devam eden) bir satırdaki kelimeleri okur .
Genel sözdizimi:
read word1 word2... remaining_words
read
o Çıkışsız satır karakteri (veya sonu girişi), böler bulana kadar bir seferde Stdin bir bayt okur o bölünme sonucu içine karmaşık kurallar ve mağazalara göre $word1
, $word2
... $remaining_words
.
Mesela şöyle bir girişte:
<tab> foo bar\ baz bl\ah blah\
whatever whatever
ve varsayılan değeri ile $IFS
, read a b c
atamak olacaktır:
$a
⇐ foo
$b
⇐ bar baz
$c
⇐ blah blahwhatever whatever
Şimdi sadece bir argüman geçerse, bu olmaz read line
. Hala var read remaining_words
. Ters eğik çizgi işleme hala devam ediyor, IFS boşluk karakterleri hala baştan ve sondan kaldırılıyor.
-r
Seçenek ters eğik çizgi işleme kaldırır. Böylece yukarıdaki aynı komut -r
yerine atamak olur
$a
⇐ foo
$b
⇐ bar\
$c
⇐ baz bl\ah blah\
Şimdi, bölünen kısım için, iki karakter sınıfı olduğunu fark etmek önemlidir $IFS
: IFS boşluk karakterleri (yani boşluk ve sekme (ve newline, burada da -d'yi kullanmadıkça önemli değil). varsayılan değerinde olmak $IFS
) ve diğerleri. Bu iki karakter sınıfının tedavisi farklıdır.
İle IFS=:
( :
değil bir IFS boşluk karakteri olmak üzere), gibi bir girdi :foo::bar::
ürüne ayrılır ""
, "foo"
, ""
, bar
ve ""
(ve ekstra ""
bunun dışında önemli değil gerçi bazı uygulamalarına read -a
). Bunu :
boşlukla değiştirirsek , bölme sadece foo
ve içine yapılır bar
. Bu öncüdür ve takip edenleri görmezden gelinir ve bunların dizileri, biri gibi davranılır. Beyaz ve beyaz olmayan karakterlerin bir araya getirilmesi durumunda ek kurallar vardır $IFS
. Bazı uygulamalar, IFS ( IFS=::
veya IFS=' '
) ' daki karakterleri ikiye katlayarak özel tedaviyi ekleyebilir / kaldırabilir .
Öyleyse burada, baştaki ve sondaki çıkmamış boşluk karakterlerinin soyulmasını istemiyorsak, bu IFS beyaz boşluk karakterlerini IFS'den kaldırmamız gerekir.
IFS boşluklu olmayan karakterlerde bile, giriş satırı bu karakterlerden birini (ve yalnızca birini) içeriyorsa ve satırdaki son karakter ( POS IFS=: read -r word
girişlerinde olduğu gibi foo:
) POSIX kabukları ile ( zsh
bazı pdksh
sürümlerde değil ) biri olarak kabul edilir foo
, bu kabuklarda, karakterler, çünkü kelime $IFS
olarak kabul edilmektedir sonlandrıcı , böylece word
içerecektir foo
değil foo:
.
Yani, read
yerleşik bir satır giriş okumak için kanonik yolu şudur:
IFS= read -r line
(çoğu read
uygulama için, sadece NUL karakteri olarak desteklenmeyen metin satırları için geçerli olduğunu unutmayın zsh
).
var=value cmd
Sözdizimini kullanmak IFS
, yalnızca söz konusu cmd
komut süresi için farklı ayarların yapıldığından emin olur .
Geçmiş notu
read
Builtin Bourne kabuk tarafından tanıtılan ve okunması zaten oldu kelimeleri değil, çizgiler. Modern POSIX mermilerinde birkaç önemli fark var.
Bourne kabuğu read
bir -r
seçeneği (Korn kabuğu tarafından getirildi) desteklemedi, bu nedenle girişi sed 's/\\/&&/g'
orada olduğu gibi bir şeyle ön işleme koymak dışında ters eğik çizgi işlemeyi devre dışı bırakmanın yolu yok.
Bourne kabuğu, iki karakter sınıfı nosyonuna sahip değildi (yine ksh tarafından getirildi). Bourne yılında IFS boşluk karakterleri ksh gibi tüm karakterlerin aynı tedavi altına kabuk, yani IFS=: read a b c
böyle bir girişi foo::bar
atayın bar
için $b
değil, boş bir dize.
Bourne kabuğunda:
var=value cmd
Eğer cmd
(gibi yerleşik bir olduğu read
olduğu), var
ayarlı kalır value
sonra cmd
sona erdi. Bu özellikle kritiktir, $IFS
çünkü Bourne kabuğunda, $IFS
sadece açılımları değil, her şeyi bölmek için kullanılır. Ayrıca, boşluk karakterini $IFS
Bourne kabuğundan kaldırırsanız, "$@"
artık çalışmaz.
Bourne kabuğunda, bir bileşik komutun yönlendirilmesi, bir alt kabukta çalışmasına neden olur (en eski sürümlerde, hatta çalışsa read var < file
veya exec 3< file; read var <&3
çalışmadıysa bile), bu nedenle Bourne kabuğunda read
terminalde kullanıcı girişi dışında herhangi bir şey için kullanılması nadirdi. (bu satır devam işleminin anlamlı olduğu yer)
Bazı Unices (HP / UX gibi, bir tane util-linux
de var) hala bir line
giriş satırı okuma komutu ( Tek UNIX Belirtimi sürüm 2'ye kadar standart bir UNIX komutu olarak kullanılmış ).
Bu, temelde, head -n 1
birden fazla satır okumadığından emin olmak için bir seferde bir byte okuması dışında aynıdır . Bu sistemlerde şunları yapabilirsiniz:
line=`line`
Tabii ki bu, yeni bir sürecin oluşturulması, bir emir yürütme ve bir boru aracılığıyla çıktısının okunması anlamına gelir, bu yüzden ksh'den çok daha az verimli IFS= read -r line
, ama yine de çok daha sezgiseldir.