2012-05-11 18 views
197

Mi piacerebbe avere il comando echo eseguito quando cat /etc/passwd | grep "sysa" non è vero.Come fare "se non vera condizione"?

Cosa sto sbagliando?

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

Il '!' Non deve essere all'interno delle parentesi? Ad esempio "[! EXPR] ' – acraig5075

+5

@ acraig5075 è valido in entrambi i casi, ma non c'è bisogno di un comando di test (che è quello che sono le parentesi) in questa dichiarazione. –

risposta

296

provare

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

grep rendimenti true se trova la destinazione di ricerca, e false se non lo fa.

Quindi NON false == true.

valutazione

if in gusci sono progettati per essere molto flessibile, e molte volte non richiede catene di comandi (come hai scritto).

Inoltre, guardando il tuo codice così com'è, il tuo uso del modulo $(...) di sostituzione di cmd deve essere lodato, ma pensa a cosa sta uscendo dal processo. Prova echo $(cat /etc/passwd | grep "sysa") per vedere cosa intendo. Puoi continuare a utilizzare l'opzione -c (count) per grep e quindi fare if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then che funziona ma è piuttosto vecchia scuola.

MA, è possibile utilizzare le nuove funzioni di shell (valutazione aritmetica) come

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

che vi dà anche il vantaggio di utilizzare gli operatori di confronto basato c-lang, ==,<,>,>=,<=,% e forse pochi altri.

In questo caso, per un commento Orwellophile, la valutazione aritmetica possono essere sbucciato ulteriormente verso il basso, come

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

O

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

Infine, v'è un premio chiamato Useless Use of Cat (UUOC). :-) Alcune persone salteranno su e giù e piangeranno gothca! Dirò semplicemente che grep può prendere un nome di file sulla sua linea cmd, quindi perché invocare processi e strutture di tubi extra quando non è necessario? ;-)

Spero che questo aiuti.

+1

È tutto piuttosto sciocco in realtà, dalla mia risposta a un molto più difficile (domanda) [http: // StackOverflow.it/a/30400327/912236] 'grep"^$ utente: "/ etc/passwd' sarebbe il modo più corretto per cercare/etc/passwd incidentalmente -' grep -v' dove * -v * inverte la ricerca se tu volevo evitare il casino di || – Orwellophile

+0

sì, beh, c'è una soluzione a un problema più efficiente, e poi c'è una risposta a una domanda specifica. Ho provato a rispondere alla domanda specifica. Grazie per le tue idee Buona fortuna a tutti. – shellter

+1

non raccogliendo le tue risposte, ci siamo divertiti molto. ho appena effettuato un controllo corretto sul nome utente, altrimenti se l'OP esegue realmente la ricerca su "sys" o somesuch, otterrà abbastanza la sorpresa. Uno in più per la strada? '(($ (cat file | grep regex | wc -l)? 0: 1))' – Orwellophile

29

Penso che possa essere semplificata in:

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

o in una singola riga di comando

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

+3

Bello, ma preferisco la risposta Mr. shellter perché è "auto documentato", è più "leggibile" l'intenzione del programmatore. –

+1

Mi piace questa versione. Che ne dici di aggiungere '1> & 2' alla fine di' echo' per stampare su 'stderr'? – Julien

+2

@ 0zkrPM Ma la versione di shellter non funziona nella shell Bourne. Otterrai '!: Not found' – ceving

2

Che cosa sto facendo di sbagliato?

$(...) detiene il valore, non lo stato di uscita, che è il motivo per cui questo approccio è sbagliato. Tuttavia, in questo caso specifico, funziona davvero perché verrà stampato sysa, il che rende la dichiarazione del test diventata realtà.Tuttavia, if ! [ $(true) ]; then echo false; fi stampa sempre false perché il comando true non scrive nulla su stdout (anche se il codice di uscita è 0). Questo è il motivo per cui deve essere riformulato su if ! grep ...; then.

Un'alternativa sarebbe cat /etc/passwd | grep "sysa" || echo error. Modifica come indicato da Alex, cat is useless here: grep "sysa" /etc/passwd || echo error.

Trovato le altre risposte piuttosto confuse, spero che questo aiuti qualcuno.

+1

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

+0

@AlexYaroshevich si, hai ragione, ho aggiunto che – Blauhirn

1

Sui sistemi Unix che lo supporta (non MacOS sembra):

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

Questo ha il vantaggio che interrogherà qualsiasi servizio di directory che può essere in uso (YP/NIS o LDAP, ecc) e il file del database delle password locale.


Il problema con grep -q "$username" /etc/passwd è che darà un falso positivo quando non c'è tale utente, ma qualcos'altro corrisponde al modello. Questo potrebbe accadere se c'è una corrispondenza parziale o esatta da qualche altra parte nel file.

Per esempio, nel mio file passwd, c'è una linea dicendo

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

Questo provocherebbe un match valido su cose come cara e enoc ecc, anche se non ci sono tali utenti sul mio sistema.

Per una soluzione grep sia corretta, è necessario analizzare correttamente il file /etc/passwd:

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

... o qualsiasi altro test simile contro il primo dei campi : delimitato da.

+0

@SDsolar Probabilmente il tuo codice non è stato eseguito da 'bash' in quel caso. – Kusalananda

1

Qui è una risposta a titolo di esempio:

Al fine di assicurarsi che i registratori di dati sono in linea uno script cron parte ogni 15 minuti che assomiglia a questo:

#!/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 
# 

... e così via per ogni data logger che si può vedere nel montaggio a http://www.SDsolarBlog.com/montage


proposito, utilizzando &>/dev/null reindirizza tutto l'output del comando, inclusi gli errori, per /dev/null

(Il condizionale richiede solo la exit status del comando ping)

Inoltre proposito, si noti che poiché cron lavori eseguiti come root c'è non è necessario utilizzare sudo ping in uno script cron.

Problemi correlati