Ich habe ein Skript, das für jede Zeile in einer Datei ein anderes Skript ausführt.
Wenn ich echo
„jedes“ drücke, $line
kann ich wie erwartet den vollständigen Inhalt der Zeile sehen.
Doch connect.sh
nur im Inneren $1
ist es so eingestellt user\ name
.
Wenn ich versuche, zu verwenden "$line"
, wird $1
am connect.sh
Ende angezeigt user\ name user\ password
.
Wie kann ich den Programmfluss so einrichten, dass reboot.sh
jede Zeile als 2 Parameter übergeben /tmp/history
wird connect.sh
?
Mit dem Endergebnis, das $1
lautet user\ name
und $2
ist user\ password
?
Neustart.sh:
if [ -e "/tmp/history" ]; then
while read -r line; do
echo $line
connect.sh $line \
&& break
done </tmp/history
fi
verbinden.sh:
echo $1
echo $2
/tmp/Geschichte:
user\ name user\ password
Antwort1
Ich gehe davon aus, dass die Backslashes dazu da sind, die beiden Leerzeichen zu maskieren, sodass sie die Werte nicht trennen.
Mit read -r line
erhalten Sie die ganze Zeile in der Variable line
, die also , mit den Backspaces line
enthält user\ name user\ password
. Es ist nicht einfach, das ohne Tricks mit aufzuteilen eval
. Ein nicht in Anführungszeichen gesetztes Wort $line
wird an Leerzeichen aufgeteilt, egal ob es Backslashs gibt oder nicht. In Anführungszeichen gesetzt, wird es zu einem Wort erweitert, wie Sie gesehen haben.
Glücklicherweise read
kann Backslashes verarbeiten und seine Eingabe in zwei (oder mehr) Variablen aufteilen. Die Variablen würden dann user name
und enthalten user password
(ohne Backslashes):
while read user pass ; do
echo "user: $user"
echo "pass: $pass"
./connect.sh "$user" "$pass"
done < file
Wenn Sie jedoch Leerzeichen im Benutzernamen und im Passwort zulassen möchten, ist es möglicherweise besser, ein anderes Trennzeichen als Leerzeichen zu verwenden. Ein Doppelpunkt ist üblich, sodass Sie eine Eingabe wie diese erhalten:
user name:user pass word
Und dann lesen Sie es mit
while IFS=: read -r user pass ; do
echo "user: $user"
echo "pass: $pass"
done < file
(Das sollte funktionieren, solange das Passwort nicht mit einem Doppelpunkt endet)
Antwort2
Wenn Sie ein Argument mit Leerzeichen haben, müssen Sie die Zeichenfolge unbedingt in doppelte Anführungszeichen setzen, um zu verhindern, connect.sh
dass sie als mehrere Argumente interpretiert wird. Möglicherweise möchten Sie die Zeichenfolge in mehrere Argumente aufteilen. Ich bin mir nicht sicher, welches Format die Zeile hat, aber Sie können möglicherweise so etwas tun:
line="user name user password"
# Split the line into space-separated tokens and store 1 and 2
UNAME=$(echo "$line" | cut -d ' ' -f 1,2)
# Split the line into space-separated tokens and store 3 and 4
UPASSWD=$(echo "$line" | cut -d ' ' -f 3,4)
echo "$UNAME"
echo "$UPASSWD"
Dies sollte gedruckt werden:
user name
user password
Sie müssen wahrscheinlich einige Anpassungen basierend auf dem tatsächlichen Format der Eingabezeile vornehmen. Wenn Ihre $line beispielsweise den Benutzernamen und das Benutzerkennwort durch ein Komma getrennt hat, können Sie Folgendes ausführen:
line="user name,user password"
# Split the line into comma-separated tokens and store 1
UNAME=$(echo "$line" | cut -d ',' -f 1)
# Split the line into comma-separated tokens and store 2
UPASSWD=$(echo "$line" | cut -d ',' -f 2)
echo "$UNAME"
echo "$UPASSWD"
Denken Sie daran: Wenn Sie einem Programm ein Argument übergeben und dieses Argument Leerzeichen enthält, müssen Sie doppelte Anführungszeichen verwenden, damit das Programm es als ein Argument erkennt.