it-swarm.com.de

Wie kann ich testen, ob eine Variable leer ist oder nur Leerzeichen enthält?

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.

Wenn param bis auf ein (oder mehrere) Leerzeichen leer ist, 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?

261
maihabunash

Beachten Sie zunächst, dass der -z test explizit für Folgendes gilt:

die Länge der Zeichenfolge ist Null

Das heißt, eine Zeichenfolge, die nur Leerzeichen enthält, sollte nicht unter -z wahr sein, da sie eine Länge ungleich Null hat.

Was Sie wollen, ist, die Leerzeichen aus der Variablen zu entfernen, indem Sie Erweiterung des Parameterersetzungsparameters :

[[ -z "${param// }" ]]

Dies erweitert die Variable param und ersetzt alle Übereinstimmungen des Musters (ein einzelnes Leerzeichen) durch nichts, sodass eine Zeichenfolge, die nur Leerzeichen enthält, zu einer leeren Zeichenfolge erweitert wird.


Das genau, wie das funktioniert ist, dass ${var/pattern/string} die erste längste Übereinstimmung von pattern durch string ersetzt. Wenn pattern mit / (wie oben) beginnt, ersetzt es all die Übereinstimmungen. Da der Ersatz leer ist, können wir den endgültigen Wert / und string weglassen:

$ {Parameter/Muster/Zeichenfolge}

Das Muster wird erweitert, um ein Muster wie bei der Dateinamenerweiterung zu erzeugen. Parameter wird erweitert und die längste Übereinstimmung von Muster gegen seinen Wert wird durch Zeichenfolge ersetzt. Wenn Muster mit '/' beginnt, werden alle Übereinstimmungen von Muster durch Zeichenfolge 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, dass diese Syntax, obwohl sie in ksh (woher sie stammt), zsh und bash vorhanden ist, nicht POSIX ist und nicht in sh -Skripten verwendet werden sollte.

304
Michael Homer

Der einfache Weg, um zu überprüfen, ob eine Zeichenfolge nur Zeichen in einem autorisierten Satz enthält, besteht darin, das Vorhandensein nicht autorisierter Zeichen zu testen. 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" umfasst den Fall einer leeren (oder nicht gesetzten) Variablen.

Möglicherweise möchten Sie nach Leerzeichen testen. 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, Tabulatoren oder Zeilenumbrüche.

Das Abgleichen eines Strings mit einem Muster mit = In [[ … ]] 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.

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

Zur Unterscheidung zwischen leer , nicht leer , 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 ASCII, aber es gibt wahrscheinlich noch einige in Ihrem Gebietsschema; einige Systeme enthalten den nicht unterbrechenden Leerzeichen (sofern verfügbar), andere nicht). Wenn Sie auch Zeichen mit vertikalem Abstand möchten (z. B. Zeilenumbruch oder Formularvorschub), ersetzen Sie [:blank:] mit [:space:].

22

Der einzige verbleibende Grund, ein Shell-Skript anstelle eines Skripts in einer guten Skriptsprache zu schreiben, besteht darin, dass extreme Portabilität ein vorrangiges Anliegen ist. Das Erbe /bin/sh ist das einzige, von dem Sie sicher sein können, dass Sie es haben, aber Perl zum Beispiel ist wahrscheinlicher 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 eingefroren haben 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 bequemerweise ein Leerzeichen, ein Tabulator und eine neue Zeile.)

(Das eingebaute printf ist selbst sehr portabel, aber es ist viel weniger mühsam, sich darauf zu verlassen, als herauszufinden, welche Variante von echo Sie haben.)

5
zwol
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
5
Guru

Der Code, den Sie gepostet haben [[ ! -z $param ]] && echo "I am not zero" druckt I am not zero wenn param entweder nicht gesetzt/undefiniert oder leer ist (in bash, ksh und zsh).

Um auch zu drucken, wenn der Parameter 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 Leittext ist gegeben durch: ${param%%[! ]*}
  • Das erweitert sich auf alle Leerzeichen vor ein beliebiges Nicht-Leerzeichen Zeichen, d. H. Alle führenden Leerzeichen.

Das Endergebnis der gesamten Erweiterung ist, dass alle führenden Leerzeichen entfernt werden.

Dieses erweiterte Ergebnis wird getestet, wenn es die Länge 0 hat.

  • Wenn das Ergebnis leer ist, war entweder die Variable leer oder
  • durch Entfernen der führenden Leerzeichen wurde es leer.

Wenn der Test wahr ist, war die Variable daher entweder bereits leer oder enthielt nur Leerzeichen.


Das Konzept lässt sich leicht auf weitere Zeichentypen erweitern. 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"
1
Isaac

Zum Testen, ob die Variable leer ist oder Leerzeichen enthält, können Sie auch diesen Code verwenden:

${name:?variable is empty}
1
pratik