memahami nilai standar IFS

10

Dalam GNU bash versi 4.2.8 saya, IFS memiliki nilai default ruang, tab, dan umpan baris secara default:

usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000  20 09 0a                                          | ..|
00000003
usr@T42 ~ $ 

Apakah ada alasan untuk IFS default seperti itu? Selain itu, utilitas mana yang menggunakan IFS selain bash built-in read?

Martin
sumber

Jawaban:

13

Variabel IFS digunakan setiap kali shell melakukan tugas yang disebut pemisahan kata . Kasus yang paling umum di mana ini digunakan adalah setelah ekspansi parameter (misalnya $var) atau substitusi perintah (misalnya $(some-command), backticks yang sudah tidak digunakan) dalam sebuah perintah. Di sini jika ekspansi berisi IFSkarakter apa pun , maka ia dipecah menjadi 'kata' yang berbeda sebelum perintah diproses. Secara efektif ini berarti bahwa karakter-karakter ini membagi teks yang diganti menjadi argumen yang berbeda (termasuk nama perintah jika variabel ditentukan terlebih dahulu).

Dengan demikian alasan untuk nilai default IFSmenjadi spasi, tab dan baris baru adalah bahwa ini adalah karakter spasi yang biasanya diharapkan untuk membagi kata.

Salah satu cara untuk mencegah pemisahan kata terjadi adalah dengan menggunakan tanda kutip ganda di sekitar ekspansi ( "$var") - sebenarnya Anda telah melakukan ini dalam pertanyaan Anda. Jika Anda tidak melakukan ini maka tidak akan ada output dari echokarena tidak akan ada argumen, hanya karakter yang memecah argumen.

Perhatikan juga bahwa dua tempat di mana pemisahan kata tidak terjadi setelah ekspansi parameter adalah dengan penugasan variabel (mis var=$othervardan var=$(somecommand)ok), dan dalam [[ ]]konstruk ( [[ $var = $othervar ]]ok, tetapi [ $var = $othervar ]harus dikutip).

Akhirnya, seperti yang pernah ditunjukkan oleh orang bijak kepada saya, kesalahpahaman yang umum adalah bahwa pencegahan pemisahan kata adalah satu - satunya alasan untuk mengutip suatu variabel. Tidak, mengutip juga mencegah ekspansi pathname atau ekspansi glob seperti yang lebih dikenal. Jika variabel berisi karakter glob seperti *maka ini dapat diperluas menjadi nama file ketika variabel digunakan tanpa tanda kutip dalam perintah. Misalnya, pertimbangkan:

var=*
echo $var

Ini akan menampilkan nama-nama file di direktori saat ini.

Seperti yang ditunjukkan Stephane di bawah ini , urutan karakter di dalam IFSadalah signifikan ketika berkembang "$*". Dari bashhalaman manual:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If
IFS is null, the parameters are joined without intervening separators.

Untuk lebih banyak contoh pemisahan kata, silakan lihat jawaban ini - https://unix.stackexchange.com/a/118444/48083

Graeme
sumber
1
Karakter pertama $IFSjuga digunakan di "$*"mana mengapa urutan itu penting.
Stéphane Chazelas
2
Perhatikan juga bahwa zshmenyertakan karakter NUL di default-nya $IFS(shell lain tidak mendukung menahan karakter NUL dalam variabel mereka).
Stéphane Chazelas