2009-05-17 7 views
28

Ein einfacher Bash Variable Test geht: Bash. Test für eine Variable nicht gesetzt, eine Funktion

${varName:? "${varName} is not defined"} 

Ich mag wieder zu verwenden, dies, indem sie sie in einer Funktion setzen. Wie bitte?

Nach versagt

# 
# Test a variable exists 
tvar(){ 
val=${1:? "${1} must be defined, preferably in $basedir"} 
if [ -z ${val} ] 
    then 
    echo Zero length value 
else 
    echo ${1} exists, value ${1} 
fi 
} 

D.h. Ich muss beenden, wenn der Test fehlschlägt.

+0

Ihr Titel sagt "nicht gesetzt", aber Ihr Beispiel Tests für "entweder nicht gesetzt oder auf die leere Zeichenfolge gesetzt". Welchen Fall interessieren Sie? –

Antwort

1

Ich habe nicht genau verstanden, was Sie brauchen. Ich versuche dich trotzdem zu antworten.

I.e. Ich muss beenden, wenn der Test fehlschlägt.

Der Code:

${varName:? "${varName} is not defined"} 

einen Nicht-Null-Exit-Code zurück, wenn es nicht eine Variable "varName" genannt ist. Der Exit-Code des letzten Befehls wird in $? gespeichert.

Über Code:

val=${1:? "${1} must be defined, preferably in $basedir"} 

Vielleicht ist es nicht zu tun, was Sie brauchen. Für den Fall, dass $1 nicht definiert ist, wird "${1}" durch nichts ersetzt. Wahrscheinlich möchten Sie die einfachen Anführungszeichen verwenden, die ${1} ohne Ersetzung buchstäblich schreibt.

val=${1:? '${1} must be defined, preferably in $basedir' 
+0

Ich möchte den Test in einer Funktion kapseln, damit ich es mit definierten SomeVariableName kapseln kann, damit ich es wiederverwenden kann. – DaveP

+0

Meine fertige Funktion, Tests für beide, nicht gesetzt und leer (Gürtel und Klammern) assertIsSet2() { wenn [[! $ {! 1} && $ {! 1-_}]] \t dann echo "$ 1 ist nicht gesetzt, Abbruch." > & 2 Ausfahrt 1 #else # \t echo $ {1} gesetzt, der Wert [$ {1}] fi : "$ {1 :? " } 1 $ ist leer, breche ab."}" Danke für die Eingabe. Ich bin wieder auf dem richtigen Weg! – DaveP

18

Was Sie suchen, ist Indirektion.

assertNotEmpty() { 
    : "${!1:? "$1 is empty, aborting."}" 
} 

, dass das Skript verursacht mit einer Fehlermeldung abgebrochen, wenn Sie so etwas tun:

$ foo="" 
$ assertNotEmpty foo 
bash: !1: foo is empty, aborting. 

Wenn Sie wollen Test nur ob foo leer ist, anstatt das Skript eines Abbruchs, verwenden Sie diese anstelle einer Funktion:

[[ $foo ]] 

Zum Beispiel:

until read -p "What is your name? " name && [[ $name ]]; do 
    echo "You didn't enter your name. Please, try again." >&2 
done 

Beachten Sie auch, dass es ein sehr wichtiger Unterschied ist zwischen einem leer und ein ungesetzt Parametern. Sie sollten darauf achten, diese Begriffe nicht zu verwechseln! Ein leerer Parameter ist einer, der gesetzt ist, aber nur auf eine leere Zeichenfolge gesetzt ist. Ein nicht gesetzter Parameter ist einer, der gar nicht existiert.

Die vorherigen Beispiele alle Test leer Parameter.Wenn Sie ungesetzt Parameter testen möchten und alle eingestellten Parameter OK prüfen, ob sie leer ist oder nicht, verwenden Sie diese:

[[ ! $foo && ${foo-_} ]] 

es in einer Funktion wie folgt verwendet:

assertIsSet() { 
    [[ ! ${!1} && ${!1-_} ]] && { 
     echo "$1 is not set, aborting." >&2 
     exit 1 
    } 
} 

Welche bricht das Skript nur, wenn der Parametername Sie einen Parameter übergeben bezeichnet, die nicht gesetzt ist:

$ (foo="blah"; assertIsSet foo; echo "Still running.") 
Still running. 
$ (foo=""; assertIsSet foo; echo "Still running.") 
Still running. 
$ (unset foo; assertIsSet foo; echo "Still running.") 
foo is not set, aborting. 
+0

Das ist der, den ich will. Vielen Dank. Ich hätte gesagt, ich sollte unruhig sein. so die Funktion, die ich will, ist assertIsSet() { [[! $ {! 1} && $ {! 1-_}]] && { echo "$ 1 ist nicht gesetzt, wird abgebrochen." > & 2 Ausfahrt 1 } } Danke. – DaveP

+0

Für neuere bash, der Test '[[! -v var]] 'wird nur dann wahr sein, wenn die Variable nicht gesetzt ist. Sieht einfacher aus als der Doppeltest in 'assertIsSet'. :) –

46

Dank lhunath‘ s Antwort wurde ich zu einem Teil der Bash führte man Seite, die ich hunderte Male übersehen habe:

 
    When not performing substring expansion, bash tests for a parameter that 
    is unset or null; omitting the colon results in a test only for a parame‐ 
    ter that is unset. 

Das bin ich aufgefordert, die folgende Wahrheitstabelle zu erstellen:

 

       | unset | set | set and | meaning 
       |  | but null | not null | 
    ============+=======+==========+==========+============================= 
    ${var-_} | T |  F | T  | not null or not set 
    ------------+-------+----------+----------+----------------------------- 
    ${var:-_} | T |  T | T  | always true, use for subst. 
    ------------+-------+----------+----------+----------------------------- 
    $var  | F |  F | T  | var is set and not null 
    ------------+-------+----------+----------+----------------------------- 
    ${!var[@]} | F |  T | T  | var is set 

Diese Tabelle führt die Spezifikation in der letzten Zeile ein. Die Bash man Seite sagt "Wenn der Name kein Array ist, wird er auf 0 erweitert, wenn der Name gesetzt ist und ansonsten auf Null." Für die Zwecke dieser Wahrheitstabelle verhält es sich gleich, auch wenn es ein Array ist.

+0

Sehr cool, aber wissen Sie, warum dies fehlschlägt, wenn var ein Array ist: 'test" $ {! Var [@]} "&& echo 'T' || echo 'F'', Fehlermeldung 'binary operator expected' – l0b0

+0

@ l0b0: Es gibt mir ein" T "oder ein" F ", je nachdem ob' var' gesetzt oder unscharf ist. Welche Shell (und ihre Version)? (Dies funktioniert nur in Bash.) Was ist der Inhalt von '$ {var [@]}' (Ausgabe von 'declare -p var')? –

+0

'Bash 4.1.5 (1) -Release (i486-pc-Linux-gnu)', 'deklarieren -a var = '([0] =" var1 "[1] =" var2 "[2] =" var3 ")". Siehe [gist] (https://gist.github.com/671067) – l0b0

1

Unsicher, ob dies ist genau das, was Sie wollen, aber ein handlicher Trick, den ich verwenden, wenn eine neue + komplexe Skript schreibst, ist „set -o“

Satzes zu verwenden -o #will das Skripts Bombe machen, wenn es findet eine unset Variable

Beispiel:

$ grep '$ 1' chex.sh

Fall "$ 1" in

./chex.sh $

./chex.sh: Linie 111: $ 1: ungebundene Variable

$ ./chex.sh foo

falsch/nein Optionen bestanden .. Beenden

+0

Meinst du 'set -u'? 'set -o' dient zum Setzen von Optionen, wie' set -o pipefail' (das solltest du auch benutzen). –

+0

'set -u' ist das gleiche wie 'set -o nomenset', was wahrscheinlich oben gemeint war. – jmanning2k

3

Diese Funktion testet auf aktuell eingestellte Variablen. Die Variable kann sogar ein Array sein. Beachten Sie, dass in bash: 0 == TRUE, 1 == FALSE.

function var.defined { 
    eval '[[ ${!'$1'[@]} ]]' 
} 

# Typical Usage of var.defined {} 

declare you="Your Name Here" ref='you'; 

read -p "What's your name: " you; 

if var.defined you; then # Simple demo using literal text 

    echo "BASH recognizes $you"; 
    echo "BASH also knows a reference to $ref as ${!ref}, by indirection."; 

fi 

unset you # have just been killed by a master :D 

if ! var.defined $ref; then # Standard demo using an expanded literal value 

    echo "BASH doesn't know $ref any longer"; 

fi 

read -s -N 1 -p "Press any key to continue..."; 
echo ""; 

Also um hier klar zu sein, testet die Funktion literalen Text.Jedesmal, wenn ein Befehl in bash aufgerufen wird, werden Variablen IM ALLGEMEINEN 'getauscht-out' oder 'substituiert' mit dem darunter liegenden Wert, es sei denn:

  • $ varRef ($) entgangen ist: \ $ varRef
  • $ varRef ist Single '$ varRef' zitiert
+0

Der Befehl 'eval' ist ein sehr riskanter Befehl, besonders wenn Sie eine vom Benutzer definierte Variable (name) erweitern. Besser zu verwenden: '[[-v Name]]', intern zu bash, viel sicherer zu verwenden. :) –

5

Sie [ -z ${parameter+word} ]

Ein Teil von man bash verwenden möchten:

Parameter Expansion 
    ... 
    In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and 
    arithmetic expansion. When not performing substring expansion, bash tests for a parameter that is unset or null; 
    omitting the colon results in a test only for a parameter that is unset. 
    ... 
    ${parameter:+word} 
      Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of 
      word is substituted. 
    ... 

mit anderen Worten:

${parameter+word} 
      Use Alternate Value. If parameter is unset, nothing is substituted, otherwise the expansion of 
      word is substituted. 

einige Beispiele:

$ set | grep FOOBAR 
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi 
it is unset 
$ declare FOOBAR 
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi 
$ FOOBAR= 
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi 
$ FOOBAR=1 
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi 
$ unset FOOBAR 
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi 
it is unset 
$ 
+0

Was macht "set | grep FOOBAR"? – AnneTheAgile

1
if set | grep -q '^VARIABLE=' 
then 
    echo VARIABLE is set 
fi 
Verwandte Themen