Bazı insanlar, readbir satırı okuma komutunun hatalı olduğu fikrine sahiptir . Değil.
readsö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
reado Çı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 catamak 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.
-rSeçenek ters eğik çizgi işleme kaldırır. Böylece yukarıdaki aynı komut -ryerine 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", "", barve ""(ve ekstra ""bunun dışında önemli değil gerçi bazı uygulamalarına read -a). Bunu :boşlukla değiştirirsek , bölme sadece foove 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 wordgirişlerinde olduğu gibi foo:) POSIX kabukları ile ( zshbazı pdkshsürümlerde değil ) biri olarak kabul edilir foo, bu kabuklarda, karakterler, çünkü kelime $IFSolarak kabul edilmektedir sonlandrıcı , böylece wordiçerecektir foodeğil foo:.
Yani, readyerleşik bir satır giriş okumak için kanonik yolu şudur:
IFS= read -r line
(çoğu readuygulama için, sadece NUL karakteri olarak desteklenmeyen metin satırları için geçerli olduğunu unutmayın zsh).
var=value cmdSözdizimini kullanmak IFS, yalnızca söz konusu cmdkomut süresi için farklı ayarların yapıldığından emin olur .
Geçmiş notu
readBuiltin 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 readbir -rseç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 cböyle bir girişi foo::baratayın bariçin $bdeğil, boş bir dize.
Bourne kabuğunda:
var=value cmd
Eğer cmd(gibi yerleşik bir olduğu readolduğu), varayarlı kalır valuesonra cmdsona erdi. Bu özellikle kritiktir, $IFSçünkü Bourne kabuğunda, $IFSsadece açılımları değil, her şeyi bölmek için kullanılır. Ayrıca, boşluk karakterini $IFSBourne 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 < fileveya exec 3< file; read var <&3çalışmadıysa bile), bu nedenle Bourne kabuğunda readterminalde 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-linuxde var) hala bir linegiriş satırı okuma komutu ( Tek UNIX Belirtimi sürüm 2'ye kadar standart bir UNIX komutu olarak kullanılmış ).
Bu, temelde, head -n 1birden 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.