bash "IFS" değişkeninin değerine bağlı olarak davranışını değiştirir


18

IFSDeğişkeni bir boşluğa ayarladığımda, bashbirden çok boşluğu bir boşluk olarak ele myprogramalır (aldığı komut satırı bağımsız değişkenlerini basan bir programdır):

IFS=" "
x="hello   hi   world"
./myprogram $x
argv[1] = hello
argv[2] = hi
argv[3] = world

Ama IFSdeğişkeni virgül olarak ayarladığımda, bashbirden fazla virgülün virgül olarak kabul edilmemesi gerekir:

IFS=","
x="hello,,,hi,,,world"
./myprogram $x
argv[1] = hello
argv[2] = 
argv[3] = 
argv[4] = hi
argv[5] = 
argv[6] = 
argv[7] = world

Neden?


Sadece referans olarak, "IFS" Dahili Alan Ayırıcı anlamına gelir .
pr1268

Yanıtlar:


21

Bu, içinde belgelenmiştir man bash. IFS'de boşluk olmayan herhangi bir karakterin tek bir örneği, bir alanı sınırlar.

Gönderen man bash:

Kabuk, IFS'nin her karakterine bir sınırlayıcı gibi davranır ve diğer genişletmelerin sonuçlarını bu karakterleri alan sonlandırıcıları olarak kullanarak kelimelere böler. IFS kaldırılırsa ya da değeri tam ise <space><tab><newline>o zaman, dizileri varsayılan <space>, <tab>ve <newline>başında ve önceki açılımları sonuçlarına sonunda göz ardı edilir ve IFS karakter dizisi değil başında veya sonunda sınırlamayı hizmet eder kelimeler. IFS varsayılandan farklı bir değere sahipse, boşluk karakteri IFS (IFS boşluk karakteri) olduğu sürece, boşluk karakterleri boşluk, sekme ve satırsonu dizileri sözcüğün başında ve sonunda yok sayılır. ). IFS'de IFS boşluk olmayan herhangi bir karakter, bitişik IFS boşluk karakterleriyle birlikte bir alanı sınırlar. Bir dizi IFS boşluk karakteri de sınırlayıcı olarak ele alınır. IFS değeri null olursa, kelime ayırma gerçekleşmez. [Vurgu eklendi.]

Örnekler: alan bölme

IFS'de boşluk karakteri yoksa, boşluklara alanlara dahil edilir:

$ ( IFS=',' x='one , two,three'; printf "<%s>\n" $x )
<one >
< two>
<three>

IFS'nin hem boşlukları hem de virgülleri varsa, boşluk dizileri, ardından virgül ve ardından boşluk dizileri tek bir ayırıcı olarak ele alınır:

$ ( IFS=' ,' x='one , two,three'; printf "<%s>\n" $x )
<one>
<two>
<three>

Virgül dizileri boş alan dizileri olarak yorumlanır:

$ ( IFS=' ,' x='one,,,two,three'; printf "<%s>\n" $x )
<one>
<>
<>
<two>
<three>

Örnekler: öndeki ve sondaki boşluk

IFS boşluk içermiyorsa, önde gelen ve sondaki boşluklar alanların içinde tutulur:

$ ( IFS=',' x='  one , two,three  ,'; printf "<%s>\n" $x )
<  one >
< two>
<three  >

IFS boşluk içeriyorsa, önde gelen veya sondaki boşluk dizileri kaldırılır:

$ ( IFS=' ,' x='  one , two,three  ,'; printf "<%s>\n" $x )
<one>
<two>
<three>

belki de "boşluk karakterleri boşluk, sekme ve satırsonu dizileri, boşluk karakteri IFS değerinde olduğu sürece sözcüğün başında ve sonunda yok sayılır"
Jeff Schaller

@JeffSchaller Mükemmel fikir: Bu konuya yeni bir bölüm ekledim.
John1024


bazı eksik değerleri olan sekmeyle ayrılmış bir dosyanız varsa ne olur? yani sekme dizilerinin tek bir sekme olarak ele alınmasını istemezsiniz. Ayrıca, alanlar virgül içerir, bu nedenle bunu ayırıcı olarak kullanamazsınız. Başka bir sınırlayıcı (sekmeler değil) kullanmak için tek çözüm mü?
Davos

@Davos tek bir sekmede ile sınırlanmış her alan ile veriler için, o kadar bu kolayca idare diğer araçları kullanmak daha doğal olabilir awkile -F'\t'seçenek veya cut. Alternatif olarak, yeni bir sürümüne bashsahipseniz, readarraybu -d$'\t'seçeneği kullanarak alanları ayrıştırabilirsiniz .
John1024
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.