Mengapa input pencetakan skrip shell ini dua kali?
Saya mengharapkan skrip untuk mengabaikan input setelah 5.
Naskah:
#! /bin/bash
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
Keluaran:
user@linux:~$ pico ifs2.sh
user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5 6
> 1 2 3 4 5 <> 6 <user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5 6 7 8 9 0
> 1 2 3 4 5 <> 6 7 8 9 0 <user@linux:~$
Dan, skrip berikut berfungsi apa pun yang disetel ke $ IFS. Mengapa?
#! /bin/bash
old="$IFS"
IFS=":"
echo "IFS = $IFS"
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
IFS="$old"
Keluaran:
user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1:2:3:4:5
> 1 2 3 4 5 <user@linux:~$
shell-script
mikeserv
sumber
sumber
printf
kapan saja dengan\c
pelarian yang terkait dengan%b
penentu format. Seperti:printf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
Jawaban:
Anda memiliki tiga masalah:
read
, jika ada lebih sedikit nama variabel daripada bidang dalam input, var terakhir akan terikat ke semua bidang yang tersisa di baris, dengan pembatas. Itu berarti bahwa Anda$e
mendapatkan5 6
contoh pertama yang tidak terduga.$a
..$e
tidak dikutip, nilainya mengalami pemisahan bidang . Jika$e
memegang "5 6
" maka itu berkembang menjadi dua argumen pada perintah.printf
menghabiskan semua argumennya, menggunakan banyak argumen sekaligus karena ada%
pergantian, berulang kali. Ini terkubur dalam dokumentasi sebagai:Dengan kata lain, jika ada argumen yang tidak digunakan itu mulai lagi dan memprosesnya dari awal juga, termasuk seluruh string format. Ini berguna ketika Anda ingin memformat seluruh array, katakan:
printf
Perintah Anda mendapat satu argumen dari masing-masing$a
..$d
, dan kemudian banyak yang tersisa dari$e
. Kapan$e
"5 6
",printf
ada dua yang berputar, yang kedua baru saja6
memformat. Saat itu5 6 7 8 9 10
ia memiliki berbagai macam pengganti untuk pencetakan kedua.Anda dapat menghindari semua ini dengan menambahkan bidang boneka tambahan
read
, dan mengutip penggantian parameter Anda (yang selalu merupakan ide bagus):Ini akan memberi:
dummy
mendapatkan semua bidang tambahan, danprintf
hanya mendapatkan lima argumen yang Anda harapkan.Pertanyaan Anda yang diedit kedua memiliki jawaban yang sama: hanya
a
mendapat nilai bilaIFS
tidak memiliki spasi. Itu berarti$b
..$e
berkembang menjadi nol, jadiprintf
hanya mendapat satu argumen. Spasi Anda dari string format dicetak, dengan tidak ada yang diganti di antaranya ("seolah-olah argumen string nol disediakan").sumber
a
memiliki nilai1 2 3 4 5
sebagai string tunggal dan akan diganti sekaligus.akan dicetak
cetakan
printf
makan semua argumen untuk memenuhi format string dan kemudian ulangi sampai semua argumen diproses.Script kedua berfungsi karena hanya
$a
ditugaskan dan oleh karena itu perintah tidak meluap ke iterasi tambahan (hanya ada satu iterasi).Perilaku ini didokumentasikan dalam teks yang dilengkapi dengan
help printf
:dan diamanatkan oleh http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
sumber