Saya mungkin memiliki sesuatu yang benar-benar salah, tetapi tampaknya meyakinkan bagi saya, bahwa menyetel IFS sebagai salah satu perintah dalam daftar pra-kerja/selesai sama sekali tidak berpengaruh.
IFS luar (di luar while konstruksi) berlaku di semua contoh yang ditunjukkan dalam skrip di bawah ini..
Apa yang terjadi di sini? Apakah saya salah paham tentang apa yang dilakukan IFS dalam situasi ini? Saya mengharapkan hasil pemisahan array seperti yang ditunjukkan pada kolom "yang diharapkan".
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- t --------tactual"
echo -e "outside t IFS tinside"
echo -e "loop t Field tloop"
echo -e "IFS NR NF t Split tIFS (actual)"
echo -e "----- -- -- t --------t-----"
IFS=$' tn'; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 1'; show "$REPLY"; done
IFS=$' tn'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't 2'; show "$REPLY"; done
IFS=$' tn'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne 't 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne 't11'; show "$REPLY"; done
echo -e "----- -- -- t --------t-----"
Keluaran:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
Jawaban yang Diterima:
(Maaf, penjelasannya panjang)
Ya, IFS variabel di while IFS=" " read; do … tidak berpengaruh pada sisa kode.
Mari kita perjelas dulu bahwa baris perintah shell menampilkan dua jenis variabel yang berbeda:
- variabel shell (yang hanya ada di dalam shell, dan lokal untuk shell)
- variabel lingkungan, yang ada untuk setiap proses. Itu biasanya disimpan pada
fork()danexec(), jadi proses anak mewarisinya.
Saat Anda memanggil perintah dengan:
A=foo B=bar command
perintah dijalankan di dalam lingkungan di mana (lingkungan) variabel A diatur ke foo dan B diatur ke bar . Tetapi dengan baris perintah ini, variabel shell saat ini A dan B dibiarkan tidak berubah .
Ini berbeda dengan:
A=foo; B=bar; command
Di sini, variabel shell A dan B didefinisikan dan perintah dijalankan tanpa variabel lingkungan A dan B didefinisikan. Nilai A dan B tidak dapat diakses dari command .
Namun, jika beberapa variabel shell adalah export -ed, variabel lingkungan yang sesuai disinkronkan dengan variabel shell masing-masing. Contoh:
export A
export B
A=foo; B=bar; command
Dengan kode ini, keduanya shell variabel dan shell lingkungan variabel diatur ke foo dan bar . Karena variabel lingkungan diwarisi oleh sub-proses, command akan dapat mengakses nilainya.
Untuk kembali ke pertanyaan awal Anda, di:
IFS='a' read
hanya read terpengaruh. Dan sebenarnya, dalam hal ini, read tidak peduli dengan nilai IFS variabel. Ini menggunakan IFS hanya ketika Anda meminta baris untuk dipisahkan (dan disimpan dalam beberapa variabel), seperti di:
echo "a : b : c" | IFS=":" read i j k;
printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"
IFS tidak digunakan oleh read kecuali jika dipanggil dengan argumen. (Sunting: Ini tidak sepenuhnya benar:karakter spasi putih, yaitu spasi dan tab, ada di IFS selalu diabaikan di awal/akhir baris input. )