Nếu tôi hiểu đúng, tôi nghĩ rằng về cơ bản bạn muốn lặp qua danh sách các giá trị, và sau đó là read
một giá trị khác trong vòng lặp.
Dưới đây là một vài lựa chọn, 1 và 2 có lẽ là tốt nhất.
1. Mô phỏng mảng bằng chuỗi
Có mảng 2D sẽ tốt, nhưng Bash thực sự không thể. Nếu các giá trị của bạn không có khoảng trắng, một cách giải quyết gần đúng đó là gắn từng bộ ba số vào một chuỗi và chia các chuỗi bên trong vòng lặp:
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
Tất nhiên bạn cũng có thể sử dụng một số dấu phân cách khác, vd for x in 1:2:3 ...
và IFS=: read a b c <<< "$x"
.
2. Thay thế đường ống bằng một chuyển hướng khác để stdin miễn phí
Một khả năng khác là read a b c
đọc dữ liệu từ một fd khác và hướng đầu vào vào đó (cái này sẽ hoạt động trong một vỏ tiêu chuẩn):
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
Và ở đây bạn cũng có thể sử dụng thay thế quy trình nếu bạn muốn lấy dữ liệu từ một lệnh: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(thay thế quy trình là tính năng bash / ksh / zsh)
3. Lấy đầu vào của người dùng từ stderr thay thế
Hoặc, theo cách khác, sử dụng một đường ống như trong ví dụ của bạn, nhưng có đầu vào của người dùng read
từ stderr
(fd 2) thay vì stdin
đường ống đến từ đâu:
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
Đọc từ stderr
là một chút kỳ lạ, nhưng thực sự thường hoạt động trong một phiên tương tác. (Bạn cũng có thể mở một cách rõ ràng /dev/tty
, giả sử bạn muốn thực sự bỏ qua bất kỳ chuyển hướng nào, đó là những thứ như less
sử dụng để có được đầu vào của người dùng ngay cả khi dữ liệu được dẫn đến nó.)
Mặc dù sử dụng stderr
như thế có thể không hoạt động trong mọi trường hợp và nếu bạn đang sử dụng một số lệnh bên ngoài thay vì read
, ít nhất bạn cần thêm một loạt các chuyển hướng vào lệnh.
Ngoài ra, hãy xem Tại sao biến của tôi cục bộ trong vòng lặp 'trong khi đọc', nhưng không phải trong một vòng lặp có vẻ tương tự khác? cho một số vấn đề liên quan ... | while
.
4. Cắt các phần của một mảng khi cần thiết
Tôi cho rằng bạn cũng có thể xấp xỉ một mảng 2D-ish bằng cách sao chép các lát của một chiều thông thường:
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
Bạn cũng có thể gán ${a[0]}
vv cho a
, b
v.v. nếu bạn muốn đặt tên cho các biến, nhưng Zsh sẽ làm điều đó độc đáo hơn nhiều .