Dikkatlice hazırlanmış bir girdi metniyle bir örneğe bakalım:
text=' hello world\
foo\bar'
Bu iki satır, ilk önce bir boşlukla başlar ve bir ters eğik çizgiyle biter. İlk önce, etrafta herhangi bir önlem alınmadan neler olacağına bakalım read(ancak herhangi bir genişleme riski olmadan printf '%s\n' "$text"dikkatli bir şekilde baskı $textyapmak için). (Aşağıda, $ kabuk istemidir.)
$ printf '%s\n' "$text" |
while read line; do printf '%s\n' "[$line]"; done
[hello worldfoobar]
readters eğik çizgi kadar yedim: ters eğik çizgi-newline yeni çizginin yok sayılmasına neden olur ve ters eğik çizgi-herhangi bir şey ilk ters eğik çizgiyi yok sayar. Ters eğik çizgilerin özel muamele görmesini önlemek için kullanırız read -r.
$ printf '%s\n' "$text" |
while read -r line; do printf '%s\n' "[$line]"; done
[hello world\]
[foo\bar]
Bu daha iyi, beklendiği gibi iki çizgimiz var. İki satır neredeyse istenen içeriği içerir: arasındaki hellove arasındaki çift boşluk worldkorunur, çünkü linedeğişken içindedir . Öte yandan, ilk alan yenildi. Bunun nedeni read, değişkenleri geçtiğin kadar çok kelime okuduğu için, son değişken satırın geri kalanını içermesi dışında - ama yine de ilk kelimeyle başlar, yani ilk boşluklar atılır.
Bu nedenle, her satırı tam anlamıyla okumak için, hiçbir kelime ayrılmasının olmadığından emin olmamız gerekir . Bunu, IFSdeğişkeni boş bir değere ayarlayarak yaparız .
$ printf '%s\n' "$text" |
while IFS= read -r line; do printf '%s\n' "[$line]"; done
[ hello world\]
[foo\bar]
Biz set nasıl Not IFS süresince özellikle readyerleşik . IFS= read -r lineSetleri değişkeni IFSspesifik olarak yürütülmesi için (boş değer) read. Bu, genel basit komut sözdiziminin bir örneğidir : bunu bir komut adı ve argümanlarının izlediği (muhtemelen boş) değişken atama dizisi (ayrıca, istediğiniz noktaya yönlendirmelerde de atabilirsiniz). Yana readyerleşik bir değişken gerçekte hiçbir zaman bir harici işlemin ortamda biter olduğu; Bununla birlikte, değeri , yürütüldüğü $IFSsürece orada readatadığımız şeydir¹. Bunun özel bir yerleşikread olmadığını unutmayın , bu nedenle atama yalnızca süresi boyunca devam eder.
Bu nedenle IFS, ona bağlı olabilecek diğer talimatların değerini değiştirmemeye özen gösteriyoruz . Bu kod, çevreleyen kodun IFSbaşlangıçta neye ayarlanmış olursa olsun çalışır ve döngü içindeki kodun kullanılması durumunda herhangi bir soruna neden olmaz IFS.
Dosyaları iki nokta üst üste ayrılmış bir yolda arayan bu kod snippet'iyle kontrast. Dosya adları listesi, bir dosyadan satır başına bir dosya adı okunur.
IFS=":"; set -f
while IFS= read -r name; do
for dir in $PATH; do
## At this point, "$IFS" is still ":"
if [ -e "$dir/$name" ]; then echo "$dir/$name"; fi
done
done <filenames.txt
Döngü olsaydı while IFS=; read -r name; do …, o for dir in $PATHzaman $PATHkolon ayrılmış bileşenlere ayrılmaz. Kod IFS=; while read …olsaydı , döngü gövdesinde IFSayarlanmamış daha da açık olurdu :.
Tabii ki, IFSçalıştırdıktan sonra değerini geri yüklemek mümkün olacaktır read. Ancak bu, önceki çabanın bilinmesini gerektirir ki bu da ekstra bir çabadır. IFS= readbasit yoldur (ve uygun şekilde, aynı zamanda en kısa yoldur).
¹ Ve eğer readtuzak çalışırken, tuzağa düşürülmüş bir sinyal tarafından kesilirse, bu POSIX tarafından belirtilmez ve pratikte kabuğa bağlıdır.
while IFS=X readEn bölmek değilX, amawhile IFS=X; readyapar ...