Wenn ich das richtig verstanden habe, denke ich, dass Sie im Grunde genommen eine Liste von Werten und dann eine read
andere innerhalb der Schleife durchlaufen möchten .
Hier sind einige Optionen, 1 und 2 sind wahrscheinlich die vernünftigsten.
1. Emulieren Sie Arrays mit Strings
2D-Arrays zu haben wäre schön, aber in Bash nicht wirklich möglich. Wenn Ihre Werte kein Leerzeichen haben, besteht eine Problemumgehung darin, jeden Satz von drei Zahlen in eine Zeichenfolge zu kleben und die Zeichenfolgen innerhalb der Schleife aufzuteilen:
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
Natürlich können Sie auch ein anderes Trennzeichen verwenden, z . B. for x in 1:2:3 ...
und IFS=: read a b c <<< "$x"
.
2. Ersetzen Sie das Rohr durch eine andere Umleitung, um stdin freizugeben
Eine andere Möglichkeit besteht darin, das read a b c
Lesen von einem anderen fd zu haben und die Eingabe darauf zu lenken (dies sollte in einer Standard-Shell funktionieren):
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
Und hier können Sie auch eine Prozessersetzung verwenden, wenn Sie die Daten von einem Befehl abrufen möchten: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(Die Prozessersetzung ist eine bash / ksh / zsh-Funktion.)
3. Nehmen Sie stattdessen Benutzereingaben von stderr entgegen
Oder umgekehrt, indem Sie eine Pipe wie in Ihrem Beispiel verwenden, aber den Benutzer read
von stderr
(fd 2) eingeben lassen, anstatt stdin
woher die Pipe stammt:
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
Das Lesen von stderr
ist etwas seltsam, funktioniert aber häufig in einer interaktiven Sitzung. (Sie können auch explizit öffnen /dev/tty
, vorausgesetzt, Sie möchten Umleitungen tatsächlich umgehen. Dies wird less
verwendet, um die Benutzereingaben auch dann abzurufen, wenn die Daten an sie weitergeleitet werden.)
Obwohl die Verwendung stderr
dieser Funktion möglicherweise nicht in allen Fällen funktioniert und Sie stattdessen einen externen Befehl verwenden read
, müssen Sie dem Befehl zumindest eine Reihe von Umleitungen hinzufügen.
Siehe auch Warum befindet sich meine Variable lokal in einer 'while read'-Schleife, aber nicht in einer anderen scheinbar ähnlichen Schleife? für einige Fragen in Bezug auf ... | while
.
4. Schneiden Sie Teile eines Arrays nach Bedarf in Scheiben
Ich nehme an, Sie könnten ein 2D-ish-Array auch approximieren, indem Sie Slices eines regulären eindimensionalen Arrays kopieren:
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
Sie können auch ${a[0]}
usw. usw. zuweisen a
, b
wenn Sie Namen für die Variablen möchten, aber Zsh würde das viel besser tun .
stderr
etwas zu benutzen ist ein bisschen schwierig, aber ich hatte die Erinnerung, dass ein Dienstprogramm es tut. Aber alles, was ich jetzt finden kann, sind solche, die nur verwenden/dev/tty
. Naja.<&2
(sowie</dev/tty
) vermeiden, aus dem Standard des Skripts zu lesen. Dies wird nicht funktionierenprintf '682\n739' | ./script
. Beachten Sie auch, dassread -p
nur in Bash arbeiten.while
Schleife, so dass Sie das stdin des Skripts sowieso nicht wirklich verwenden können ...read -u
ist ebenfalls bash, kann aber durch Weiterleitungen ersetzt werden und<<<
in Der erste ist ebenfalls nicht Standard, aber das ist etwas schwieriger zu umgehen.Es gibt nur einen
/dev/stdin
, derread
überall dort liest, wo er verwendet wird (standardmäßig).Die Lösung besteht darin, anstelle von 1 (
/dev/stdin
) einen anderen Dateideskriptor zu verwenden .Vom Code-Äquivalent (in Bash) zu dem, was Sie gepostet haben [1] (siehe unten),
fügen Sie einfach
0</dev/tty
(zum Beispiel) hinzu, um aus dem "echten" tty zu lesen:Bei der Ausführung:
Eine andere Alternative ist die Verwendung
0<&2
(was seltsam erscheinen mag, aber gültig ist).Beachten Sie, dass das Lesen von
/dev/tty
(auch0<&2
) den Standard des Skripts umgeht. Dadurch werden die Werte aus dem Echo nicht gelesen:Andere Lösungen
Was benötigt wird, ist, eine Eingabe auf eine andere fd (Dateideskriptor) umzuleiten.
Gültig in ksh, bash und zsh:
Oder mit exec:
Eine Lösung, die in sh
<<<
funktioniert ( funktioniert nicht):Aber das ist wahrscheinlich leichter zu verstehen:
1 Einfacherer Code
Ihr Code lautet:
Ein vereinfachter Code (in Bash) lautet:
Welche, wenn ausgeführt, druckt:
Das zeigt nur, dass die Variable d von derselben gelesen wird
/dev/stdin
.quelle
Mit
zsh
können Sie es stattdessen schreiben:Für 2D-Arrays siehe auch die
ksh93
Shell:quelle