Ich habe eine Variable, die einen Wert wie diesen hat
line=dog,/path1,/path2
Ich möchte aus dem Wert eine Variable erstellen; d. h. es dog
sollte die Variable sein und ich möchte die folgende Ausgabe erhalten:
dog=/path1,/path2
dog1=/path1
dog2=/path2
Wenn ich das habe, line=bull,/val1,/val2
brauche ich die folgende Ausgabe.
bull=/val1,/val2
bull1=/val1
bull2=/val2
Beachten Sie, dass line
nur drei durch Kommas getrennte Werte vorhanden sind.
Antwort1
Ich denke, das ist es, was Sie versuchen:
line='dog,/path1,/path2'
IFS=', ' read -r -a dog <<< "$line"
echo "$dog"
dog
echo "${dog[1]}"
/path1
echo "${dog[2]}"
/path2
Dies setzt voraus, dass Ihre Shell Bash ist.
Antwort2
Hier ist eine Bash-zentrierte Lösung:
IFS=, read -r -a vars <<<"$line"
printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"
Die erste Zeile teilt Ihre $line
Variable anhand der Kommas in Teile auf. Die zweite Zeile, von innen nach außen arbeitend:
- gibt den ersten Wert (z. B. 'Hund') aus, das Gleichheitszeichen, dann die zweiten beiden Werte,
- gibt den ersten Wert mit dem angehängten
1
Gleichheitszeichen aus, dann den zweiten Wert, - gibt den ersten Wert aus, mit dem Suffix
2
, Gleichheitszeichen, dann den dritten Wert, printf
diese drei Zeichenfolgen, durch Zeilenumbrüche getrennt.
Diese Antwort ist, wie Ihre Frage, fest auf drei Werte in codiert $line
.
Beispiele für Eingabe und Ausgabe (die führenden $
sind die Shell-Eingabeaufforderungen):
$ line=dog,/path1,/path2
$ IFS=, read -r -a vars <<<"$line"
$ printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"
dog=/path1,/path2
dog1=/path1
dog2=/path2
Sie können die printf-Ausgabe ganz einfach in eine Datei umleiten.
Antwort3
Wenn Sie verwenden bash
, können Sie etwa Folgendes tun (mit zusätzlichen echo
Anweisungen, um zu zeigen, was in jeder Phase geschieht):
$ line=dog,/path1,/path2
$ newline=$(printf "%s\n" "$line" |
perl -n -e 'BEGIN {$count=1};
my ($var,@values) = split /,/;
print "$var=" . join(",",@values);
foreach (@values) {
printf "%s%i=\"%s\" ",$var, $count++, $_
}')
$ echo "$newline"
dog=/path1,/path2 dog1=/path1 dog2=/path2
$ declare $newline
$ declare | grep '^dog'
dog=/path1,/path2
dog1=/path1
dog2=/path2
Dabei wird durch Kommas perl
getrennt $line
. Das erste Feld wird in gespeichert $var
, der Rest in einem Array namens @values
. Anschließend wird eine Ausgabe erzeugt, die für die Verwendung mit dem Bash- declare
Befehl zum Festlegen von Variablen geeignet ist.
Beachten Sie, dass $newline
die Zeile nicht in doppelte Anführungszeichen gesetzt ist und auch nicht gesetzt werden sollte declare
. Wenn es in doppelte Anführungszeichen gesetzt wird, declare
wird nur ein Argument erhalten, statt drei, die durch Leerzeichen getrennt sind.
Ein unangenehmer Nebeneffekt des fehlenden Zitierens ist, dass diedeclare
WILLEschlägt fehl, wenn einer der Feldwerte Leerzeichen usw. enthält, z. B. line=dog,/path /with / spaces,/path2
. Sie können dies bei Bedarf beheben, indem Sie entsprechende Anführungszeichen aus den print
und printf
Anweisungen im perl
Skript ausgeben. Und/oder indem Sie es $newline
als Bash-Array statt als Zeichenfolge definieren. Dies bleibt dem Leser als Übung überlassen, da ich bereits genug von dem hier verwendeten Prinzip/der hier verwendeten Technik gezeigt habe.
Wenn Sie sie als exportierte Variablen deklarieren möchten, verwenden Sie:
declare -x $newline
help declare
Weitere Einzelheiten finden Sie unter.
Übrigens ksh
können Sie in typeset
anstelle von verwenden declare
. typeset
wird auch von unterstützt, bash
gilt jedoch als veraltet (siehe help typeset
in bash
).
dog[0]=/path1,/path2
Und zum Schluss: Sind Sie sicher, dass Sie nicht lieber eine Shell-Array-Variable (z. B. , dog[1]=/path1
, und ) anstelle separater Variablen verwenden möchten dog[2]=/path2
? Für solche Dinge gibt es sie nämlich.
Antwort4
Sie könnten so etwas tun. Ich definiere die Zeile wie Sie. Als nächstes analysiere ich das erste durch Kommas getrennte Token aus der Zeile (ich gehe hier davon aus, dass dies für einen Variablennamen gültig ist). Dann konstruiere ich zwei neue Variablen basierend auf dem ersten Token und weise sie dem zweiten und dritten durch Kommas getrennten Token aus der Zeile zu.
line="dog,/path1,/path2"
first="$(echo "${line}" | awk -F, '{ print $1 }')"
eval "${first}1=$(echo "${line}" | awk -F, '{ print $2 }')"
eval "${first}2=$(echo "${line}" | awk -F, '{ print $3 }')"
echo "${dog1}"
/path1
echo "${dog2}"
/path2