So schlage ich vor, Sie sollten es tun, und ich werde erklären, warum, aber zuerst möchte ich über etwas anderes sprechen ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Viele der anderen hier angebotenen Lösungen scheinen darauf hinzudeuten, dass Sie den Inhalt einer Shell-Variablen irgendwie beeinflussen können, indem Sie ihre Erweiterungsmethoden ändern. Ich kann Ihnen versichern, dass dies nicht der Fall ist.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
AUSGABE
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
Was Sie oben sehen, ist zuerst eine feldgeteilte Erweiterung, dann ein Bericht über die Byteanzahl für die Quellvariable der Erweiterung, dann eine durch Anführungszeichen getrennte Erweiterung und dieselbe Byteanzahl. Während die Ausgabe unterschiedlich sein kann, $string
ändert sich der Inhalt der Shell-Variablen nur bei Zuweisung.
Was mehr ist, wenn Sie nicht verstehen, warum dies so ist, werden Sie früher als später auf einige sehr böse Überraschungen stoßen. Versuchen wir es noch einmal, aber unter etwas anderen Bedingungen.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
Gleich $string
- andere Umgebung.
AUSGABE
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
Die Feldaufteilung erfolgt anhand der in definierten Feldbegrenzer $IFS
. Es gibt zwei Arten von Begrenzern - $IFS
Leerzeichen und $IFS
alles andere. Standardmäßig $IFS
wird der Wertebereichsregisterkarte Zeilenumbruch zugewiesen - dies sind die drei möglichen $IFS
Leerzeichenwerte. Sie lässt sich jedoch leicht ändern, wie Sie oben sehen, und kann drastische Auswirkungen auf die Field-Split-Erweiterungen haben.
$IFS
Whitespace wird durch Sequenzierung in ein einzelnes Feld zerlegt - und aus diesem Grund wird echo
eine Erweiterung, die eine beliebige Folge von Leerzeichen $IFS
enthält, wenn sie ein Leerzeichen enthält, nur zu einem einzelnen Leerzeichen ausgewertet, da echo
die Argumente für Leerzeichen verkettet werden. Nicht-Whitespace-Werte werden jedoch nicht auf die gleiche Weise entfernt, und jeder vorkommende Begrenzer erhält immer ein Feld für sich - wie aus der obigen Stuff- Erweiterung hervorgeht.
Das ist nicht das Schlimmste. Betrachten Sie diesen anderen $string
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
AUSGABE
* * * * * * 30
* * * * * * 30
Sieht ok aus, oder? Nun, lassen Sie uns die Umgebung noch einmal ändern.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
AUSGABE
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Woah.
Standardmäßig erweitert die Shell Dateinamen-Globs, wenn sie mit ihnen übereinstimmen können. Dies geschieht nach der Parametererweiterung und der Aufteilung der Felder in der angegebenen Reihenfolge. Daher ist jede nicht in Anführungszeichen gesetzte Zeichenfolge auf diese Weise anfällig. Sie können dieses Verhalten mit set -f
deaktivieren, wenn Sie möchten, aber jede POSIX-kompatible Shell wird standardmäßig immer glob sein.
Dies ist die Art von Dingen, mit denen Sie konfrontiert sind, wenn Sie Erweiterungen in Anführungszeichen setzen, um sie Ihren Einzugspräferenzen anzupassen. Und $string
trotzdem ist der tatsächliche Wert für unabhängig von seinem Expansionsverhalten immer noch der Wert, den Sie zuletzt zugewiesen haben. Kommen wir also zum ersten Punkt zurück.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
AUSGABE
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Ich glaube, dies ist eine weitaus vernünftigere Möglichkeit, die Shell-Syntax an Ihre Einzugspräferenzen anzupassen. Was ich oben mache, ist die Zuweisung jeder einzelnen Zeichenfolge zu einem Positionsparameter - auf den jeweils durch eine Zahl wie $1
oder verwiesen werden kann ${33}
- und anschließend die Zuweisung ihrer verketteten Werte zur $var
Verwendung des speziellen Shell-Parameters $*
.
Dieser Ansatz ist jedoch nicht immun gegen $IFS
. Dennoch halte ich seine Beziehung $IFS
in dieser Hinsicht für einen zusätzlichen Nutzen. Erwägen:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
AUSGABE
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
Wie Sie sehen können, wird $*
jedes Argument im "$@"
ersten Byte im verkettet $IFS
. Wenn Sie also den Wert speichern, während er $IFS
unterschiedlich zugewiesen ist, erhalten Sie für jeden gespeicherten Wert unterschiedliche Feldbegrenzer. Was Sie oben sehen, ist übrigens der Literalwert für jede Variable. Wenn Sie überhaupt kein Trennzeichen möchten, würden Sie Folgendes tun:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
AUSGABE
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67