Cómo mantener el último estado de salida después de la testing

¿Es posible mantener inalterado el último estado de salida del command ( $? ) Después de una testing?

Por ejemplo, me gustaría hacer:

 command -p sudo ... [ $? -ne 1 ] && exit $? 

La última exit $? debe devolver el estado de salida de sudo, pero en su lugar siempre devuelve 0 (el código de salida de la testing).

¿Es posible hacer eso sin una variable temporal?

Otro ejemplo para aclarar más:

  spd-say "$@" [ $? -ne 127 ] && exit $? 

En este caso, quiero salir solo si se encuentra el primer command (código de salida! = 127 ). Y quiero salir con el código de salida actual de spd-say (puede que no sea 0 ).

EDIT: olvidé mencionar que prefiero una solución de queja POSIX para una mejor portabilidad.

Uso este constructo en scripts en los que deseo proporcionar alternativas para el mismo command. Por ejemplo, mira mi script crc32 .

El problema con las variables temporales es que pueden sombrear otras variables, y para evitar eso debe usar nombres largos, lo que no es bueno para la legibilidad del código.

$_ funcionará en (al less) dash interactivos, bash , zsh , ksh (aunque aparentemente no en un enunciado condicional, como se solicitó) y mksh shells. De ellos, que yo sepa, solo bash y zsh también lo pueblan en un shell con guiones. No es un parámetro POSIX, pero es bastante portátil para cualquier shell moderno e interactivo.

Para una solución más portátil, puede hacer:

 command -p sudo ... eval '[ "$?" = 127 ] || exit '"$?" 

¿Qué básicamente te permite expandir el valor inicial de $? en la queue del guión incluso antes de probar su valor a la cabeza.

Pero de todos modos, como pareces estar probando si el command sudo se puede encontrar en la cadena de ruta de acceso portátil incorporada del shell con command , creo que podrías hacerlo un poco más directamente. Además, para que quede claro, el command no probará la location de los arguments a sudo , por lo que solo es sudo y no invoca nada, que es relevante para ese valor de retorno.

Y de todos modos, si eso es lo que estás tratando de hacer:

 command -pv sudo >/dev/null || handle_it command -p sudo something or another 

… funcionaría bien como una testing sin posibilidad de errores en el command. Las ejecuciones de sudo vuelven de tal manera que pueden sesgar los resultados de su testing.

Hay varias opciones para manejar el estado de salida de manera confiable sin gastos generales, dependiendo de los requisitos reales.

Puede save el estado de salida usando una variable:

 command -p sudo ... rc=$? [ "$rc" -ne 1 ] && echo "$rc" 

Puede verificar directamente el éxito o el fracaso:

 if command -p sudo ... then echo success else echo failure fi 

O use una construcción de case para diferenciar el estado de salida:

 command -p sudo ... case $? in (1) ... ;; (127) ... ;; (*) echo $? ;; esac 

con el caso especial preguntado en la pregunta:

 command -p sudo ... case $? in (1) :;; (*) echo $?;; esac 

Todas esas opciones tienen la ventaja de que se ajustan al estándar POSIX.

(Nota: para ilustrar, utilicé los commands de echo anteriores; los reemploop por declaraciones de exit apropiadas para que coincidan con la function solicitada).

 command -p ... test 1 -ne $? && exit $_ 

Use $_ , que se expande hasta el último argumento del command anterior.

Puede definir (y usar) una function de shell:

 check_exit_status() { [ "$1" -ne 1 ] && exit "$1" } 

Entonces

 command -p sudo ... check_exit_status "$?" 

Podría decirse que esto es "hacer trampa", ya que hace una copy de $? en la list de arguments check_exit_status .

Esto puede parecer un poco incómodo, y lo es. (Eso sucede a veces cuando se imponen restricciones arbitrarias a los problemas.) Esto puede parecer inflexible, pero no lo es. Puede hacer check_exit_status más complejo, agregando arguments que le digan qué testing (s) hacer en el valor de estado de salida.

Para responder a su pregunta directa, no, no es posible mantener $? inalterado Y este es uno de esos casos en los que sospecho que te estás enfocando en el problema equivocado. Una variable temporal es la forma estándar y preferida para get el efecto que está buscando. Es tan estándar que sugeriría abandonar (o repensar) cualquier razón que piense que tiene para no querer usar una; Dudo mucho que valga la complejidad adicional agregada por cualquier otro método.

Si solo preguntas por simple curiosidad, entonces la respuesta es no.

Aquí está mi fragment de código para conservar un estado de salida anterior sin salir del script / shell actual

 EXIT_STATUS=1 if [[ $EXIT_STATUS == 0 ]] then echo yes else (exit $EXIT_STATUS) fi