Jika saya benar ini, saya pikir Anda pada dasarnya ingin mengulang daftar nilai, dan kemudian yang read
lain dalam loop.
Berikut beberapa opsi, 1 dan 2 mungkin yang paling ramah.
1. Emulasi array dengan string
Memiliki array 2D akan menyenangkan, tetapi tidak benar-benar mungkin di Bash. Jika nilai Anda tidak memiliki spasi putih, satu solusi untuk perkiraan yaitu menempel setiap set dari tiga angka ke dalam string, dan membagi string di dalam loop:
for x in "1 2 3" "4 5 6"; do
read a b c <<< "$x";
read -p "Enter a number: " d
echo "$a - $b - $c - $d ";
done
Tentu saja Anda bisa menggunakan pemisah lain juga, misalnya for x in 1:2:3 ...
dan IFS=: read a b c <<< "$x"
.
2. Ganti pipa dengan pengalihan lain untuk membebaskan stdin
Kemungkinan lain adalah memiliki read a b c
pembacaan dari fd lain dan mengarahkan input ke sana (ini harus bekerja dalam shell standar):
while read a b c <&3; do
printf "Enter a number: "
read d
echo "$a - $b - $c - $d ";
done 3<<EOF
1 2 3
4 5 6
EOF
Dan di sini Anda juga dapat menggunakan substitusi proses jika Anda ingin mendapatkan data dari perintah: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(substitusi proses adalah fitur bash / ksh / zsh)
3. Ambil input pengguna dari stderr sebagai gantinya
Atau, sebaliknya, menggunakan pipa seperti pada contoh Anda, tetapi minta input pengguna read
dari stderr
(fd 2) alih-alih dari stdin
mana pipa itu berasal:
echo $'1 2 3\n4 5 6' |
while read a b c; do
read -u 2 -p "Enter a number: " d
echo "$a - $b - $c - $d ";
done
Membaca dari stderr
agak aneh, tetapi sebenarnya sering bekerja dalam sesi interaktif. (Anda juga dapat membuka secara eksplisit /dev/tty
, dengan asumsi Anda ingin benar-benar memintas pengalihan, itulah hal-hal seperti apa yang less
digunakan untuk mendapatkan input pengguna bahkan ketika data disalurkan ke sana.)
Meskipun menggunakan stderr
seperti itu mungkin tidak berfungsi dalam semua kasus, dan jika Anda menggunakan beberapa perintah eksternal read
, Anda setidaknya perlu menambahkan banyak pengalihan ke perintah.
Juga, lihat Mengapa variabel saya lokal dalam satu loop 'sambil membaca', tetapi tidak dalam loop lain yang tampaknya serupa? untuk beberapa masalah tentang ... | while
.
4. Iris bagian array sesuai kebutuhan
Saya kira Anda juga bisa memperkirakan array 2D-ish dengan menyalin irisan satu dimensi biasa:
data=(1 2 3
4 5 6)
n=3
for ((i=0; i < "${#data[@]}"; i += n)); do
a=( "${data[@]:i:n}" )
read -p "Enter a number: " d
echo "${a[0]} - ${a[1]} - ${a[2]} - $d "
done
Anda juga dapat menetapkan ${a[0]}
dll. a
, b
Dll jika Anda ingin nama untuk variabel, tetapi Zsh akan melakukannya dengan lebih baik .
stderr
seperti itu agak sedikit menjengkelkan, tetapi saya memiliki ingatan bahwa beberapa utilitas melakukannya. Tapi yang bisa saya temukan sekarang adalah yang hanya digunakan/dev/tty
. Baiklah.<&2
(dan juga</dev/tty
) menghindari membaca dari stdin skrip. Ini tidak akan berfungsiprintf '682\n739' | ./script
. Perhatikan juga bahwaread -p
hanya berfungsi di bash.while
loop itu, jadi Anda tidak bisa benar-benar menggunakan skrip stdin ...read -u
juga bash, tetapi dapat diganti dengan pengalihan, dan<<<
di yang pertama juga tidak standar, tapi itu agak sulit untuk diselesaikan.Hanya ada satu
/dev/stdin
,read
akan membacanya dari mana saja di mana ia digunakan (secara default).Solusinya adalah menggunakan beberapa deskriptor file lain, bukan 1 (
/dev/stdin
).Dari kode setara (dalam bash) ke apa yang Anda posting [1] (lihat di bawah)
cukup tambahkan
0</dev/tty
(misalnya) untuk membaca dari tty "real":Pada eksekusi:
Alternatif lain adalah menggunakan
0<&2
(yang mungkin tampak aneh, tetapi valid).Perhatikan bahwa read from
/dev/tty
(juga0<&2
) akan memotong stdin dari skrip, ini tidak akan membaca nilai dari echo:Solusi lain
Yang diperlukan adalah mengarahkan satu input ke beberapa fd lainnya (deskriptor file).
Berlaku dalam ksh, bash, dan zsh:
Atau, dengan exec:
Solusi yang bekerja di sh (
<<<
tidak bekerja):Tapi ini mungkin lebih mudah dimengerti:
1 kode sederhana
Kode Anda adalah:
Kode yang disederhanakan (dalam bash) adalah:
Yang, jika dijalankan, mencetak:
Yang hanya menunjukkan bahwa var d sedang dibaca dari yang sama
/dev/stdin
.sumber
Dengan
zsh
, Anda dapat menulisnya sebagai gantinya:Untuk array 2D, lihat juga
ksh93
shell:sumber