2009-05-17 9 views
28

Un simple análisis de la variable va Bash:Bash. Prueba para un borrando la variable, usando una función

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

me gustaría volver a usar esto, poniéndolo en una función. ¿Cómo por favor?

Siguiendo falla

# 
# 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 
} 

es decir, Necesito salir si la prueba falla.

+0

Su título dice "desactivada", pero su ejemplo prueba "ya sea desarmado o se establece en la cadena vacía". ¿Qué caso te importa? –

Respuesta

1

No entiendo exactamente qué es lo que necesita. Estoy tratando de responderte a pesar de esto.

I.e. Necesito salir si la prueba falla.

El código:

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

devolverá un código de salida cero no cuando no hay una variable llamada "varName". El código de salida del último comando se guarda en $?.

información sobre su código:

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

Tal vez no está haciendo lo que necesita. En el caso de que $1 no esté definido, el "${1}" se sustituirá por nada. Probablemente desee utilizar las comillas simples que literalmente escribe ${1} sin sustitución.

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

Quiero encapsular la prueba en una función, para permitirme llamarlo con definido SomeVariableName para que pueda volver a utilizarlo. – DaveP

+0

Mi función finalizada, pruebas para unset y empty (cinturón y llaves) assertIsSet2() { if [[! $ {! 1} && $ {! 1-_}]] \t luego echo "$ 1 no está configurado, abortando". > & 2 salida 1 #else # \t echo $ {1} está establecido, el valor de [$ {1}] fi : "$ {1 :?! " } $ 1 está vacía, abortando."}" Gracias por la entrada. ¡Estoy de vuelta en la pista! – DaveP

18

Lo que estás buscando es indirección.

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

Eso hace que la secuencia de comandos para abortar con un mensaje de error si haces algo como esto:

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

Si lo que desea es prueba si foo está vacía, en lugar de abortar el guión, utilizar esto en vez de una función:

[[ $foo ]] 

Por ejemplo:

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

Además, tenga en cuenta que hay una diferencia muy importante entre un vacío y un parámetro de desarmar . ¡Debe tener cuidado de no confundir estos términos! Un parámetro vacío es uno que está establecido pero que acaba de establecerse en una cadena vacía. Un parámetro no establecido es uno que no existe en absoluto.

Todos los ejemplos anteriores prueban parámetros vacíos.Si desea probar la no se ha establecido parámetros y considerar todos los parámetros establecidos bien, si están vacíos o no, utilizar esto:

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

utilizarlo en una función como esta:

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

que sólo aborta la secuencia de comandos cuando el nombre único parámetro que indica un parámetro que no se establece:

$ (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

Ese es el que quiero. Gracias. Debería haber dicho unset. por lo que la función que quiero es assertIsSet() { [[! $ {! 1} && $ {! 1-_}]] && { echo "$ 1 no está establecido, abortando". > & 2 exit 1 } } Gracias. – DaveP

+0

Para más nuevo bash, la prueba '[[! -v var]] 'será verdadero solo cuando la var esté desarmada. Parece más fácil que la doble prueba en 'assertIsSet'. :) –

46

Gracias a lhunath' s respuesta, se llevó a una parte de la página Bash man que he pasado por alto cientos de veces:

 
    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. 

Esto me impulsó a crear la siguiente tabla de verdad:

 

       | 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 

esta tabla introduce la especificación en la última fila. La página de Bash man dice "Si el nombre no es una matriz, se expande a 0 si el nombre está establecido y nulo en caso contrario". A los efectos de esta tabla de verdad, se comporta igual incluso si se trata de una matriz.

+0

Muy bien, pero ¿sabes por qué esto falla cuando var es una matriz: 'prueba" $ {! Var [@]} "&& echo 'T' || echo 'F'', mensaje de error 'operador binario esperado' – l0b0

+0

@ l0b0: Me da una" T "o una" F "dependiendo de si' var' está establecido o no. ¿Qué shell (y su versión)? (Esto solo funciona en Bash.) ¿Cuál es el contenido de '$ {var [@]}' (salida de 'declare -p var')? –

+0

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

1

No está seguro si esto es exactamente lo que quiere, pero un truco muy útil que utilizo al escribir un nuevo guión + compleja es usar "set -o" conjunto

-o #will hacer la bomba cuando la escritura se encuentra una variable unset

Ejem:

$ grep chex.sh '$ 1'

case "$ 1" en

$ ./chex.sh

./chex.sh: Línea 111: $ 1: sin consolidar variables

$ foo ./chex.sh

incorrecta/no opciones pasadas ... saliendo de

+0

¿Quieres decir 'set -u'? 'set -o' es para configurar opciones, como' set -o pipefail' (que también deberías usar). –

+0

'set -u' es lo mismo que 'set -o nounset', que probablemente fue pensado anteriormente. – jmanning2k

3

Esta función prueba las variables que ESTÁN ACTUALMENTE configuradas. La variable puede ser incluso una matriz. Tenga en cuenta que en 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 ""; 

Para que quede claro aquí, la función prueba el texto literal.Cada vez que un comando se llama en bash, las variables son generalmente o 'sustituido' 'de salida intercambian' con el valor subyacente a menos que:

  • $ Ref.var ($) se escapó: \ $ Ref.var
  • $ Ref.var es único citado '$ Ref.var'
+0

El comando 'eval' es un comando muy arriesgado, especialmente cuando se expande un conjunto de var por el usuario (nombre). Es mejor usar: '[[-v nombre]]', interno a bash, mucho más seguro de usar. :) –

5

desea utilizar [ -z ${parameter+word} ]

Una parte de man bash:

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. 
    ... 

en otras palabras:

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

algunos ejemplos:

$ 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

¿Qué hace "set | grep FOOBAR"? – AnneTheAgile

1
if set | grep -q '^VARIABLE=' 
then 
    echo VARIABLE is set 
fi 
Cuestiones relacionadas