Ich habe den folgenden Codeausschnitt, in dem ich Folgendes beabsichtige:
Durchlaufe die Schleife fünfmal;
hole eine Zeile aus einer Datei (bei jeder Iteration muss die nächste Zeile abgerufen werden);
verwende die Zeile als Titel für eine Datei;
setze einen Zeitstempel an den Anfang;
verwende die Zeile als Argument für Ping; drucke einige Sätze, die den Benutzer über den Fortschritt des Codes informieren;
Die Iteration funktioniert bereits.
Wenn ich den sed-Teil überspringe, funktioniert alles, aber ich führe den Ping 5 Mal gegen dasselbe Ziel aus.
Jede Zeile der Datei hosts.txt hat eine einzelne IP-Adresse, die ich anpingen möchte.
for ((i>=1;i<=5;i++))
do
sed -n "$i p" hosts.txt | read output
touch "$output.txt"
date >> "$output.txt"
printf "\nComeçando o teste de $output."
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done
Ich glaube, das Problem liegt darin, dass ich etwas bei der Sed-Syntax falsch mache. Wenn ich es direkt bei Bash versuche sed -n 1p hosts
, bekomme ich die erste Zeile. Da diese Zahl aber $i sein muss, interpretiert Bash ip als Variable, wenn ich $i direkt vor p setze, anstatt als Variable i plus Argument p dahinter.
Wie kann ich dieses Verhalten korrigieren, ohne die Sache erneut durcheinander zu bringen?
Antwort1
Ich gehe davon aus, dass Sie Bash verwenden, daher sollte das Folgende besser funktionieren:
for ((i=1;i<=5;i++))
do
sed -n "$i p" hosts.txt | (
read output
touch "$output.txt"
date >> "$output.txt"
printf "\nComeçando o teste de $output."
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
)
done
Ihr Problem ist bash
, dass wie bei den meisten externen Shell-Interpretern ksh
alle Pipeline-Komponenten in einer Subshell abgelegt werden, sodass die output
Variable nach der Festlegung sofort verloren geht.
Beachten Sie auch, dass ich Ihre for
Schleife korrigiert habe, die beim Schreiben ein undefiniertes Verhalten aufwies, weil die i
Variable nicht initialisiert wurde.
Antwort2
Das Problem ist, wie Sie bemerkt haben, dass sowohl i
als auch ip
gültige Variablennamen sind. Wenn Sie also den Wert verwenden möchten, $i
auf den unmittelbar das Zeichen folgt p
, können Sie geschweifte Klammern verwenden, um klar abzugrenzen, wo der Variablenname beginnt und endet:
sed -n "${i}p" hosts.txt | read output
Antwort3
Eine etwas einfachere Lösung ist
for ((i=1; i<=5; i++))
do
read output
date >> "$output.txt"
printf "\nComeçando o teste de %s." "$output"
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt
Beachten Sie das < hosts.txt
am Ende der letzten Zeile, nach dem done
. Dies wird hosts.txt
einmal geöffnet und liest nur die ersten fünf Zeilen daraus. Wie von don_crissti erwähnt, bedeutet die Ausführung in der Schleife, dass Sie die Datei fünfmal sed … hosts.txt | read output
lesen . Da dies parallel zum Rest der Schleife (nicht in einer Pipeline) erfolgt, hat der restliche Code in der Schleife Zugriff auf den aus der Datei gelesenen Wert von . Außerdem (wie Don ebenfalls anmerkte) brauchen Sie kein ; erstellthosts.txt
read output
output
touch
command >> file
file
sofern es nicht bereits existiert.
Beachten Sie, dass dieser Code die neuen Informationen an eine Ihrer hostname.txt
Dateien anfügt, wenn diese bereits vorhanden ist. Wenn Sie alte Daten verwerfen und von vorne beginnen möchten, tun Sie dies date > "$output.txt"
anstelle von date >> "$output.txt"
.
Seien Sie vorsichtig, wenn Sie unbekannte Daten direkt an übergeben printf
. Im (unwahrscheinlichen?) Fall, dass einer Ihrer „Hostnamen“ ein enthält %
, wird Ihr Code diesen Namen verstümmeln. Es ist besser, fremde Daten an zu übergeben %s
(um eine Zeichenfolge zu drucken).
Sie geben nicht an, ob Sie nur die ersten fünf Zeilen der hosts.txt
Datei lesen und dann aufhören möchten oder ob Sie die gesamte Datei lesen möchten und zufällig wissen, dass sie fünf Zeilen lang ist. Wenn Sie die gesamte Datei lesen möchten, tun Sie einfach
while read output
do
date >> "$output.txt"
printf "\nComeçando o teste de %s." "$output"
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt
Wenn Sie das Ende der Datei erreichen, read output
schlägt die Anweisung fehl und die Schleife wird beendet.