2012-05-11 17 views
197

Me gustaría tener el comando echo ejecutado cuando cat /etc/passwd | grep "sysa" no es verdadero.¿Cómo hacer "si no es verdad"?

¿Qué estoy haciendo mal?

if ! [ $(cat /etc/passwd | grep "sysa") ]; then 
     echo "ERROR - The user sysa could not be looked up" 
     exit 2 
fi 
+4

¿Debería el '!' No estar dentro de los corchetes? es decir ''! EXPR] ' – acraig5075

+5

@ acraig5075 es válido de cualquier manera, pero no hay necesidad de un comando de prueba (que es lo que son los corchetes) en esta declaración en absoluto. –

Respuesta

296

tratar

if ! grep -q sysa /etc/passwd ; then 

grep vuelve true si encuentra el objetivo de búsqueda y false si no lo hace.

Así que NO false == true.

if La evaluación en shells está diseñada para ser muy flexible, y muchas veces no requiere cadenas de comandos (como usted ha escrito).

Además, mirando su código como está, su uso de la forma $(...) de la sustitución de cmd es encomiable, pero piense en lo que está saliendo del proceso. Pruebe echo $(cat /etc/passwd | grep "sysa") para ver lo que quiero decir. Puede llevar eso más allá al usar la opción -c (conteo) para grep y luego hacer if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then, que funciona, pero es más bien de la vieja escuela.

PERO, puede utilizar las características más nuevas de concha (evaluación aritmética) como

if ! (($(grep -c "sysa" /etc/passwd) == 0)) ; then ...` 

que también le da la ventaja de utilizar los operadores de comparación basados ​​c-Lang, ==,<,>,>=,<=,% y tal vez algunos otros.

En este caso, por un comentario de Orwellophile, la evaluación aritmética puede ser recortado aún más, como

if ! (($(grep -c "sysa" /etc/passwd))) ; then .... 

O

if ((! $(grep -c "sysa" /etc/passwd))) ; then .... 

Por último, hay un premio llamado Useless Use of Cat (UUOC). :-) Algunas personas saltan hacia arriba y hacia abajo y lloran gothca! Solo diré que grep puede tomar un nombre de archivo en su línea de cmd, entonces, ¿por qué invocar procesos extra y construcciones de tubería cuando no es necesario? ;-)

Espero que esto ayude.

+1

En realidad, todo es bastante tonto, desde mi respuesta a una mucho más difícil (pregunta) [http: // stackoverflow.com/a/30400327/912236] 'grep"^$ usuario: "/ etc/passwd' sería la forma más correcta de buscar/etc/passwd incidently -' grep -v' donde * -v * invierte la búsqueda si quería evitar el desorden de || – Orwellophile

+0

sí, está resolviendo un problema de la manera más eficiente, y luego está respondiendo una pregunta específica. Intenté responder la pregunta específica. Gracias por tus ideas Buena suerte a todos. – shellter

+1

sin elegir sus respuestas, las disfruté bastante. Acabo de lanzar un cheque debidamente acotado en el nombre de usuario, de lo contrario, si el OP realmente busca en "sys" o algo así, obtendrá la sorpresa. uno más por el camino? '(($ (cat archivo | grep regex | wc -l)? 0: 1))' – Orwellophile

29

creo que se puede simplificar en:

grep sysa /etc/passwd || { 
    echo "ERROR - The user sysa could not be looked up" 
    exit 2 
} 

o en una sola línea de comandos

$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }

+3

Agradable, pero prefiero la respuesta Mr. Shellter porque es "auto-documentado", es más "legible" la intención del programador. –

+1

Me gusta esta versión. ¿Qué hay de agregar '1> & 2' al final de su' echo' para imprimir en 'stderr'? – Julien

+2

@ 0zkrPM Pero la versión de shell no funciona en el shell Bourne. Obtendrá '!: Not found' – ceving

2

¿qué estoy haciendo mal?

$(...) mantiene el valor , no el estado de salida, es por eso que este enfoque es erróneo. Sin embargo, en este caso específico, de hecho funciona porque se imprimirá sysa, lo que hace que la declaración de prueba se haga realidad.Sin embargo, if ! [ $(true) ]; then echo false; fi siempre imprimiría false porque el comando true no escribe nada en stdout (incluso si el código de salida es 0). Es por eso que necesita ser reformulado a if ! grep ...; then.

Una alternativa sería cat /etc/passwd | grep "sysa" || echo error. Edite como Alex señaló, cat is useless here: grep "sysa" /etc/passwd || echo error.

Encontré las otras respuestas bastante confusas, espero que esto ayude a alguien.

+1

o 'grep" sysa "/ etc/passwd || echo error' –

+0

@AlexYaroshevich sí, tienes razón, agregué que – Blauhirn

1

En los sistemas Unix que lo soporta (no parece macOS):

if getent passwd "$username" >/dev/null; then 
    printf 'User %s exists\n' "$username" 
else 
    printf 'User %s does not exist\n' "$username" 
fi 

Esto tiene la ventaja de que se consulta cualquier servicio de directorio que pueden estar en uso (YP/NIS o LDAP, etc.) y el archivo de base de datos de contraseñas local.


El problema con grep -q "$username" /etc/passwd es que va a dar un falso positivo cuando no hay tal usuario, sino otra cosa coincide con el patrón. Esto podría suceder si hay una coincidencia parcial o exacta en algún otro lugar del archivo.

Por ejemplo, en mi archivo passwd, hay una línea que dice

build:*:21:21:base and xenocara build:/var/empty:/bin/ksh 

esto provocaría un partido válido en cosas como cara y enoc etc., a pesar de que no existen tales usuarios de mi sistema.

Para una solución grep sea correcto, tendrá que analizar correctamente el archivo /etc/passwd:

if cut -d ':' -f 1 /etc/passwd | grep -qxF "$username"; then 
    # found 
else 
    # not found 
fi 

... o cualquier otra prueba similar contra el primero de los campos : -delimited.

+0

@SDsolar Probablemente tu código no sea ejecutado por 'bash' en ese caso. – Kusalananda

1

Aquí es una respuesta a modo de ejemplo:

Con el fin de asegurarse de que los registradores de datos en línea son un script cron sale cada 15 minutos que tiene este aspecto:

#!/bin/bash 
# 
if ! ping -c 1 SOLAR &>/dev/null 
then 
    echo "SUBJECT: SOLAR is not responding to ping" | ssmtp [email protected] 
    echo "SOLAR is not responding to ping" | ssmtp [email protected] 
else 
    echo "SOLAR is up" 
fi 
# 
if ! ping -c 1 OUTSIDE &>/dev/null 
then 
    echo "SUBJECT: OUTSIDE is not responding to ping" | ssmtp [email protected] 
    echo "OUTSIDE is not responding to ping" | ssmtp [email protected] 
else 
    echo "OUTSIDE is up" 
fi 
# 

... y así sucesivamente para cada registrador de datos que se puede ver en el montaje en http://www.SDsolarBlog.com/montage


su información, utilizando &>/dev/null redirige todo el resultado del comando, incluyendo los errores, a /dev/null

(La única condición requiere que el exit status del comando ping)

también FYI, tenga en cuenta que, dado que cron trabajos se ejecutan como root existe no es necesario utilizar sudo ping en un script cron.

Cuestiones relacionadas