Die folgende Bash-Syntax überprüft, ob param
nicht „leer“ ist:
[[ ! -z $param ]]
Zum Beispiel:
param="" [[ ! -z $param ]] && echo "I am not zero"
Keine Ausgabe und es ist in Ordnung.
Aber wenn param
ist bis auf ein (oder mehrere) Leerzeichen leer, dann ist der Fall anders:
param=" " # one space [[ ! -z $param ]] && echo "I am not zero"
„Ich bin nicht Null „wird ausgegeben.
Wie kann ich den Test ändern, um Variablen, die nur Leerzeichen enthalten, als leer zu betrachten?
Kommentare
- Von
man test
:-z STRING - the length of STRING is zero
. Wenn Sie alle Leerzeichen in$param
entfernen möchten, Verwenden Sie${param// /}
- WOW Es ist keine einfache
trim()
-Funktion integriert Irgendwelche * nix überhaupt? So viele verschiedene Hacks, um etwas so Einfaches zu erreichen … - @ADTC $ (sed ‚ s / ^ \ s + | \ s + $ // g ‚ < < < $ string) scheint mir einfach zu sein. Warum das Rad neu erfinden?
- Weil es glänzender sein könnte
- Nur zu beachten, dass
[[ ! -z $param ]]
test ! -z $param
.
Antwort
Beachten Sie zunächst, dass die -z
Test ist explizit für:
Die Länge der Zeichenfolge ist Null
Das heißt, eine Zeichenfolge, die nur Leerzeichen enthält, sollte nicht ist unter -z
wahr, da es eine Länge ungleich Null hat.
Sie möchten die Leerzeichen mit der Erweiterung der Musterersetzungsparameter :
[[ -z "${param// }" ]]
Dies erweitert die param
variabel und ersetzt alle Übereinstimmungen des Musters (ein einzelnes Leerzeichen) durch nichts, sodass eine Zeichenfolge, die nur Leerzeichen enthält, zu einem erweitert wird leere Zeichenfolge.
Die , wie das funktioniert ist, dass ${var/pattern/string}
ersetzt die erste längste Übereinstimmung von pattern
durch string
. Wenn pattern
mit /
(wie oben) beginnt, werden alle Übereinstimmungen ersetzt. Da der Ersatz leer ist, können wir den endgültigen Wert /
und den Wert string
weglassen:
$ {parameter / pattern / string}
Das pattern wird erweitert, um ein Muster wie bei der Dateinamenerweiterung zu erzeugen. Parameter wird erweitert und die längste Übereinstimmung von Muster mit seinem Wert wird durch Zeichenfolge ersetzt. Wenn pattern mit „/“ beginnt, werden alle Übereinstimmungen von pattern durch string ersetzt. Normalerweise wird nur das erste Spiel ersetzt. … Wenn string null ist, werden Übereinstimmungen von pattern gelöscht und das / folgende pattern kann weggelassen werden.
Nach all dem haben wir ${param// }
, um alle Leerzeichen zu löschen.
Beachten Sie dies jedoch vorhanden in ksh
(woher es stammt), zsh
und bash
ist diese Syntax nicht vorhanden POSIX und sollte nicht in sh
-Skripten verwendet werden.
Kommentare
- use
sed
sagten sie … nurecho
die Variable, die sie sagten … - Hmm. Wenn es
${var/pattern/string}
ist, sollte ‚ nicht[[ -z ${param/ /} ]]
mit dem Abstand zwischen den Schrägstrichen sein um das Muster und nichts danach die Zeichenfolge zu sein? - @JesseChisholm “ Da die Ersetzung leer ist, können wir das endgültige / und den Zeichenfolgenwert „; “ Wenn string null ist, werden Übereinstimmungen von pattern gelöscht und das / folgende pattern kann sein weggelassen. “
- @MichaelHomer Die Antwort
[[ -z "${param// }" ]]
sieht sicher aus wie diepattern
ist leer und diereplacement string
ist ein einzelnes Leerzeichen. AH! Ich sehe es jetztif pattern begins with a slash
Ich habe diesen Teil verpasst. Das Muster lautet also/
, und die Zeichenfolge wird weggelassen und ist daher leer. Danke. - Bash-Hinweis: Wenn in set -o nounset (set -u) ausgeführt wird und param nicht gesetzt ist (anstatt null oder mit Leerzeichen gefüllt), wird ein ungebundener Variablenfehler generiert. (set + u; …..) würde diesen Test ausnehmen.
Antwort
Der einfache Weg Um zu überprüfen, ob eine Zeichenfolge nur Zeichen in einem autorisierten Satz enthält, müssen Sie prüfen, ob nicht autorisierte Zeichen vorhanden sind.Anstatt zu testen, ob die Zeichenfolge nur Leerzeichen enthält, testen Sie daher, ob die Zeichenfolge ein anderes Zeichen als Leerzeichen enthält. In bash, ksh oder zsh:
if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters other than space" else echo "\$param consists of spaces only" fi
„Besteht nur aus Leerzeichen“ enthält den Fall einer leeren (oder nicht gesetzten) Variablen.
Möglicherweise möchten Sie nach Leerzeichen suchen. Verwenden Sie [[ $param = *[^[:space:]]* ]]
, um die Gebietsschemaeinstellungen oder eine explizite Liste von Leerzeichen zu verwenden, auf die Sie testen möchten, z. [[ $param = *[$" \t\n"]* ]]
zum Testen auf Leerzeichen, Tabulator oder Zeilenumbruch.
Abgleichen eines Strings mit einem Muster mit =
innerhalb von [[ … ]]
ist eine ksh-Erweiterung (auch in bash und zsh vorhanden). In jedem Bourne / POSIX-Stil können Sie das Konstrukt case
verwenden, um eine Zeichenfolge mit einem Muster abzugleichen. Beachten Sie, dass Standard-Shell-Muster !
verwenden, um einen Zeichensatz zu negieren, anstatt ^
wie in den meisten Syntaxen für reguläre Ausdrücke.
case "$param" in *[!\ ]*) echo "\$param contains characters other than space";; *) echo "\$param consists of spaces only";; esac
Zum Testen auf Leerzeichen ist die Syntax $"…"
spezifisch für ksh / bash / zsh. Sie können diese Zeichen buchstäblich in Ihr Skript einfügen (beachten Sie, dass eine neue Zeile in Anführungszeichen stehen muss, da Backslash + Newline zu nichts erweitert wird) oder sie generieren, z. B.
whitespace=$(printf "\n\t ") case "$param" in *[!$whitespace]*) echo "\$param contains non-whitespace characters";; *) echo "\$param consists of whitespace only";; esac
Kommentare
- Dies ist fast ausgezeichnet – aber es beantwortet die gestellte Frage noch nicht. Derzeit können Sie den Unterschied zwischen einer nicht gesetzten oder leeren Shell-Variablen und einer Variablen erkennen, die nur Leerzeichen enthält. Wenn Sie meinen Vorschlag akzeptieren, fügen Sie das Parametererweiterungsformular hinzu, das noch nicht von einer anderen Antwort konvergiert wurde, die explizit eine Shell-Variable auf ihre Einstellung testet – ich meine
${var?not set}
– diesen Test besteht und überlebt würde sicherstellen, dass eine Variable, die mit Ihrer*)
case
übereinstimmt, beispielsweise eine endgültige Antwort bewirkt. - Korrektur – Dies würde in der Tat die ursprünglich gestellte Frage beantworten, wurde jedoch inzwischen so bearbeitet, dass sich die Bedeutung der Frage grundlegend ändert und Ihre Antwort daher ungültig wird.
- Sie benötigen
[[ $param = *[!\ ]* ]]
inmksh
.
Antwort
POSIXly:
case $var in (*[![:blank:]]*) echo "$var contains non blank";; (*) echo "$var contains only blanks or is empty or unset" esac
Zur Unterscheidung zwischen blank und non-blank , leer , nicht gesetzt :
case ${var+x$var} in (x) echo empty;; ("") echo unset;; (x*[![:blank:]]*) echo non-blank;; (*) echo blank esac
[:blank:]
steht für Zeichen mit horizontalem Abstand (Leerzeichen und Tabulator in A. SCII, aber es gibt wahrscheinlich noch ein paar mehr in Ihrem Gebietsschema; Einige Systeme enthalten den nicht unterbrechenden Bereich (sofern verfügbar), andere nicht „t“. Wenn Sie auch Zeichen mit vertikalem Abstand (wie Zeilenumbruch oder Formularvorschub) möchten, ersetzen Sie [:blank:]
mit [:space:]
.
Kommentare
- POSIXly ist ideal, da es mit dem (wohl besseren) funktioniert. dash.
-
zsh
scheint ein Problem mit[![:blank:]]
zu haben, es löst:b
ist ein ungültiger Modifikator. Insh
undksh
emulieren wird ein Ereignis ausgelöst, das für[
- @cuonglm, was haben Sie versucht?
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
ist für mich in Ordnung. Das nicht gefundene Ereignis ist nur für interaktive Shells. - @St é phaneChazelas: Ah, richtig, ich habe es mit interaktiven Shells versucht. Der ungültige Modifikator
:b
ist etwas seltsam. - @FranklinYu ist unter OS / X
sh
erstellt mit--enable-xpg-echo-default
und--enable-strict-posix-default
, um Unix-kompatibel zu sein (was Ausgabe einer Registerkarte).
Antwort
Der einzige verbleibende Grund zum Schreiben Ein Shell-Skript anstelle eines Skripts in einer guten -Skriptsprache ist, wenn extreme Portabilität ein vorrangiges Anliegen ist. Das Legacy /bin/sh
ist das einzige, von dem Sie sicher sein können, dass Sie es haben, aber Perl zum Beispiel ist eher plattformübergreifend verfügbar als Bash. Schreiben Sie daher niemals Shell-Skripte, die Funktionen verwenden, die nicht wirklich universell sind – und denken Sie daran, dass mehrere proprietäre Unix-Anbieter ihre Shell-Umgebung vor POSIX.1-2001 .
Es gibt eine tragbare Möglichkeit, diesen Test durchzuführen, aber Sie müssen tr
verwenden:
[ "x`printf "%s" "$var" | tr -d "$IFS"`" = x ]
(Der Standardwert von $IFS
ist zweckmäßigerweise ein Leerzeichen, eine Registerkarte und eine neue Zeile.)
(Die printf
integriert ist selbst sehr portabel, aber es ist viel weniger mühsam, sich darauf zu verlassen, als herauszufinden, welche Variante von echo
Sie haben.)
Kommentare
- Das ‚ ist etwas verworren.Die übliche tragbare Methode zum Testen, ob eine Zeichenfolge bestimmte Zeichen enthält, ist mit
case
. - @ Gilles Ich glaube nicht, dass es ‚ möglich ist, einen
case
Glob zu schreiben Erkennen Sie eine Zeichenfolge, die entweder leer ist oder nur Leerzeichen enthält. (Mit einem regulären Ausdruck wäre es einfach, abercase
führt
keine regulären Ausdrücke aus. Das Konstrukt in Ihrer Antwort wird ‚ funktioniert nicht, wenn Sie sich für Zeilenumbrüche interessieren.)
case $param in *[![:space:]]*) …
. Wenn Sie auf IFS
Zeichen testen möchten, können Sie das Muster *[$IFS]*
verwenden. <space><tab><newline>
und berühren es dann nie wieder. Ich dachte, dass ‚ eine Ablenkung sein würde. .profile
, die von vielen Bourne-Shells ausgeführt wurde. Natürlich wird [$IFS]
‚ nicht das tun, was beabsichtigt war, wenn IFS
bestimmte Nicht-Standardwerte aufweist Werte (leer (oder nicht gesetzt), die ]
enthalten, beginnend mit !
oder ^
) . Antwort
if [[ -n "${variable_name/[ ]*\n/}" ]] then #execute if the the variable is not empty and contains non space characters else #execute if the variable is empty or contains only spaces fi
Kommentare
- Dadurch werden alle Leerzeichen entfernt, nicht nur ein einzelnes Leerzeichen, oder? danke
Antwort
Zum Testen, ob die Variable leer ist oder Leerzeichen enthält, können Sie auch diesen Code verwenden:
${name:?variable is empty}
Kommentare
- Ich denke, Ihre Antwort wurde abgelehnt, weil die “ oder Leerzeichen enthalten “ ist nicht wahr.
- Seien Sie vorsichtig – das tötet die aktuelle Shell. Besser in eine (: $ {Subshell?}). Außerdem – das wird an stderr geschrieben – möchten Sie wahrscheinlich umleiten. Und am wichtigsten , das den tatsächlichen Wert der Variablen ‚ ergibt, wenn er nicht nicht gesetzt oder null ist. Wenn dort ‚ ein Befehl enthalten ist, haben Sie ihn einfach ausgeführt. ‚ führt diesen Test am besten auf
:
aus. - wie die Shell getötet wird. und Sie können dies auch testen. Definieren Sie zuerst
name=aaaa
und führen Sie dann diesen Befehl aus.echo ${name:?variable is empty}
gibt den Wert des Variablennamens aus und führt nun diesen Befehlecho ${name1:?variable is empty}
gibt -sh: name1 aus: Variable ist leer - Ja –
echo ${name:?variable is empty}
wird entweder als$name
‚ als Nicht-Null-Wert ausgewertet oder wird die Shell beenden. Aus dem gleichen Grund tun Sie ‚ nichtprompt > $randomvar
und${var?}
– if dort ‚ ist ein Befehl drin, ‚ wird wahrscheinlich ausgeführt – und Sie geben ‚ Ich weiß nicht, was es ist. Eine interaktive Shell muss nicht ‚ beendet werden – weshalb Ihre ‚ t nicht ausgeführt wird. Wenn Sie jedoch einige Tests sehen möchten, gibt es hier viele . . Dieser ist nicht ‚ nicht ganz so lang …
Antwort
Der von Ihnen veröffentlichte Code [[ ! -z $param ]] && echo "I am not zero"
gibt I am not zero
aus, wenn param ist entweder nicht gesetzt / undefiniert oder leer (in bash, ksh und zsh).
Zu auch print, wenn param nur Leerzeichen enthält (Leerzeichen entfernen), POSIXly (für einen größeren Bereich von Shells):
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
Erläuterung:
- Ein
${param# … }
entfernt einen führenden Text. - Dieser führende Text wird gegeben durch:
${param%%[! ]*}
- Dieser wird auf alle Leerzeichen vor ein beliebiges Nicht-Leerzeichen Zeichen, dh alle führenden Leerzeichen.
Das Endergebnis der gesamten Erweiterung ist, dass alle führenden Leerzeichen entfernt werden.
Dieses erweiterte Ergebnis wird auf Länge 0 getestet.
- Wenn das Ergebnis leer ist, war entweder die Variable leer oder
- entfernt die führenden Leerzeichen machte es leer.
Wenn der Test wahr ist, war die Variable entweder bereits leer oder enthielt nur Leerzeichen.
Das Konzept lässt sich leicht auf weitere erweitern Zeichentypen. Um auch Registerkarten einzuschließen, platzieren Sie eine explizite Registerkarte in dem Klammerausdruck:
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
oder verwenden Sie eine Variable mit den Zeichen, die Sie entfernen müssen:
var=$" \t" # in ksh, bash, zsh [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"
oder Sie können einen POSIX „Zeichenklassenausdruck“ verwenden (leer bedeutet Leerzeichen und Tabulator):
[ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
Antwort
Um zu überprüfen, ob die Variable nur Leerzeichen enthält, einschließlich einer mehrzeiligen Variablen , versuchen Sie Folgendes:
[[ $var = *[$" \t\n"]* ]]
Oder mit xargs:
[[ -z $(echo $var | xargs) ]]
Oder mit sed:
[[ -z $(sed "/^$/d" <<< $var) ]]
Antwort
Versuchen Sie Folgendes:
$ [[ -z \`echo $n\` ]] && echo zero zero