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. )