¿Cómo se extrae el estado de salida de un comando en una variable?

14

Empecé a aprender Bash hace un par de días.

Estoy tratando de obtener un estado de salida de grepexpresión en una variable como esta:

check=grep -ci 'text' file.sh

y la salida que obtuve es

No command '-ic' found

¿Debo hacerlo con un comando de tubería?

omri gilhar
fuente
66
Para el estado de salida, puede examinar $?justo después de que finalice el comando.
coffeMug
y puede examinar la matriz PIPESTATUS si desea el estado de uno de los comandos en una tubería.
cas

Respuestas:

26

Su comando,

check=grep -ci 'text' file.sh

será interpretado por el shell como "ejecutar el comando -cicon los argumentos texty file.sh, y establecer la variable checkal valor grepen su entorno".


El shell almacena el valor de salida del comando ejecutado más recientemente en la variable ?. Puede asignar su valor a una de sus propias variables como esta:

grep -i 'PATTERN' file
check=$?

Si desea actuar sobre este valor, puede usar su checkvariable:

if [ "$check" -eq 0 ]; then
    # do things for success
else
    # do other things for failure
fi

o puede omitir el uso de una variable separada y tener que inspeccionar $?todos juntos:

if grep -q -i 'pattern' file; then
  # do things (pattern was found)
else
  # do other things (pattern was not found)
fi

(tenga en cuenta -qque indica grepque no envíe nada y que salga tan pronto como algo coincida; no estamos realmente interesados ​​en qué coincide aquí)

O, si solo quiere "hacer cosas" cuando no se encuentra el patrón :

if ! grep -q -i 'pattern' file; then
  # do things (pattern was not found)
fi

Guardar $?en otra variable solo es necesario si necesita usarlo más tarde, cuando el valor en $?se ha sobrescrito, como en

mkdir "$dir"
err=$?

if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
    printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
    exit "$err"
fi

En el fragmento de código anterior, $?se sobrescribirá el resultado de la [ "$err" -ne 0 ] && [ ! -d "$dir" ]prueba. Guardarlo aquí solo es realmente necesario si necesitamos mostrarlo y usarlo con exit.

Kusalananda
fuente
4

Su pregunta no está clara, pero según el código que ha enviado, parece que desea que la variable checkalmacene el estado de salida del grepcomando. La forma de hacerlo es correr

grep -ci 'text' file.sh
check=$?

Cuando se ejecuta un comando desde un shell, su estado de salida se pone a disposición a través del parámetro especial concha, $?.

POSIX (el estándar para sistemas operativos similares a Unix) documenta esto en su especificación para el shell y la implementación de Bash se documenta en Parámetros especiales .

Como eres un nuevo alumno, te recomiendo que comiences con un buen libro y / o un tutorial en línea para obtener los conceptos básicos. No se recomiendan las recomendaciones de recursos externos en los sitios de Stack Exchange, pero sugeriría Lhunath y la Guía Bash de GreyCat .

Anthony G - justicia para Monica
fuente
4

Le ha dicho a bash que establezca la variable check=grepen el entorno que pasa al comando

-ci 'text' file.sh

pero cino existe

Creo que pretendía encerrar ese comando en marcas de retroceso, o entre paréntesis precedidos por un signo de dólar, cualquiera de los cuales asignaría el recuento de cuántas líneas se encontró 'texto' (sin distinción de mayúsculas y minúsculas) en el archivo:

check=`grep -ci 'text' file.sh`

check=$(grep -ci 'text' file.sh)

Ahora $checkdebería ser 0 si no hay coincidencias, o positivo si hubo coincidencias.

Monty Harder
fuente
1

¿Confundido por qué usar -c al verificar la salida? Se usa para verificar cuántas veces se empareja algo, no si tiene éxito o no.

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)

pero en este ejemplo

check="$(grep --silent -i 'text' file.sh; echo $?)"

No genera nada excepto un código de salida, que luego se repite. Este es el resultado que utiliza la verificación de variables. También lo prefiero porque es una sola línea.

Puede reemplazar --silent con -q. Lo uso ya que no estás interesado en la salida grep, solo si funcionó o no.

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s  or  --no-messages  option.
          (-q is specified by POSIX.)

$ check=$(echo test | grep -qi test; echo $?) # check variable is now set
$ echo $check
0
$ check=$(echo null | grep -qi test; echo $?)
$ echo $check
1
Miati
fuente
1

La forma correcta de asignar la salida del comando grep a una variable es como se menciona en @ monty-harder:

check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)

Aunque para asignar el estado de salida de este comando a una variable, debe usar el parámetro de shell $?justo después de ejecutar el comando como se muestra a continuación:

grep -ci 'text' file.sh
check=$?
echo $check
Curioso
fuente