
/bin/sh
Ist es in einer POSIX-Shell oder in der Bourne-Shell (wie in Solaris 10 ) möglich, etwas wie Folgendes zu haben:
a='some var with spaces and a special space'
printf "%s\n" $a
Und mit der Standardeinstellung IFS
erhalten Sie:
some
var
with
spaces
and
a
special space
Das heißt, den Leerraum zwischen special
und space
durch eine Kombination aus Anführungszeichen oder Escapezeichen schützen?
Die Anzahl der Wörter a
ist im Voraus nicht bekannt, sonst würde ich etwas wie Folgendes versuchen:
a='some var with spaces and a special\ space'
printf "%s\n" "$a" | while read field1 field2 ...
Der Kontext istdieser Fehlerin Cassandra gemeldet, wo OP versucht hat, eine Umgebungsvariable festzulegen, die Optionen für die JVM angibt:
export JVM_EXTRA_OPTS='-XX:OnOutOfMemoryError="echo oh_no"'
Im Skript, das Cassandra ausführt, das POSIX sh und Solaris sh unterstützen muss:
JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS"
#...
exec $NUMACTL "$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" $props "$class"
Meiner Meinung nach besteht der einzige Ausweg darin, ein Skript zu verwenden, das den echo oh_no
Befehl umschließt. Gibt es eine andere Möglichkeit?
Antwort1
Nicht wirklich.
Eine Lösung besteht darin, ein Zeichen als Feldtrennzeichen zu reservieren. Natürlich ist es nicht möglich, dieses Zeichen, egal, was es ist, in eine Option einzuschließen. Tabulator und Zeilenumbruch sind offensichtliche Kandidaten, wenn die Quellsprache es einfach macht, sie einzufügen. Ich würde Multibyte-Zeichen vermeiden, wenn Sie Portabilität wünschen (z. B. unterstützen Bindestrich und BusyBox keine Multibyte-Zeichen).
Wenn Sie auf IFS-Aufteilung angewiesen sind, vergessen Sie nicht, die Platzhaltererweiterung mit zu deaktivieren set -f
.
tab=$(printf '\t')
IFS=$tab
set -f
exec java $JVM_EXTRA_OPTS …
Ein anderer Ansatz besteht darin, eine Anführungszeichensyntax einzuführen. Eine sehr verbreitete Anführungszeichensyntax besteht darin, dass ein Backslash das nächste Zeichen schützt. Der Nachteil der Verwendung von Backslashs besteht darin, dass sie von so vielen verschiedenen Tools als Anführungszeichen verwendet werden, dass es manchmal schwierig sein kann, herauszufinden, wie viele Backslashs Sie benötigen.
set java
eval 'set -- "$@"' $(printf '%s\n' "$JVM_EXTRA_OPTS" | sed -e 's/[^ ]/\\&/g' -e 's/\\\\/\\/g') …
exec "$@"
Antwort2
Wenn Sie Bash oder Ähnliches verwenden, würde ein Array den Zweck erfüllen:
a=(some var with spaces and a 'special space')
Da die POSIX-Shell diese jedoch nicht hat, ist der beste interne Ansatz, den ich sehe, die Verwendung eines speziellen Leerzeichens. Das geschützte Leerzeichen (U+00A0) ist für diesen Zweck gut geeignet, erfordert jedoch eine Vereinbarung über den Zeichensatz des Skripts, da es sich nicht um ASCII handelt.
a="some var with spaces and a special space"
# this is a non-breaking space ------^
echo "$a" \
| while read word; do printf '%s\n' ${word} | sed 's@ @ @g'; done
# this is a non-breaking space ----------------------^
Dies gibt aus:
some
var
with
spaces
and
a
special space
Im Moment bin ich nicht sicher, wie ich dies in eine Variablenerweiterung einbinden kann (dazu ist eine Untershell erforderlich), aber dies sollte einen Ausgangspunkt für weitere Untersuchungen bieten.