2012-02-24 15 views
10

Ho uno script che emette circa 10 righe ogni volta se viene eseguito. Il contenuto di queste linee varia.È possibile inserire una frase if?

Mi piacerebbe molto essere in grado di grep nell'output e fare cose diverse a seconda dell'output.

In pseudo questo è quello che vorrei fare

cat /etc/password | \\ 
if [ grep "root" $STDOUT ]; then 
    echo "root is found" 

elif [ grep "nobody" $STDOUT ]; then 
    echo "nobody is found" 

fi 

Qui ho ho usato cat /etc/password come esempio, ma dovrebbe essere sostituito con i miei script di cui sopra.

Il problema è: come posso ottenere l'uscita da cat /etc/password nelle condizioni if/elif?

+1

Forse awk o Perl sono più adatte per il vostro compito .. – bew

+2

non utilizzare 'cat' se l'intenzione non è né visualizzata né concatenata. Qui puoi semplicemente dare il file nella riga di comando grep, perché è accettato, altrimenti puoi semplicemente reindirizzare il file ('<'). – Benoit

+2

Non è necessario continuare la linea dopo '|', '&&' e '||' –

risposta

5

Come consigliato da @Benoit, è sufficiente utilizzare direttamente grep.

Come note @larsmans, è possibile evitare una doppia lettura del file leggendolo in una variabile una volta.

data la disponibilità di bash lo farei in questo modo:

password=$(< /etc/passwd) 

if grep -q root <<< "$password" ; then 
    echo root found 
elif grep -q nobody <<< "$password" ; then 
    echo nobody found 
fi 

Una lettura del file, uno o due invocazioni di grep, nessun altro processo o sottoshell lanciati.

+0

Soluzione molto interessante. Perché hai 'IFS =' sulla prima riga? –

+2

In bash, puoi semplicemente dire 'password = $ (

+0

Un buon punto di glenn, l'avevo dimenticato. – Sorpigal

3

basta fare:

if grep -q "root" /etc/passwd ; then 
    ... 
fi 

che svolgerà i comandi ... se il codice di uscita grep è 0.

ricordare che \[ is a external command, probabilmente situato a /usr/bin/[ (di solito si tratta di un legame difficile da test e quando invocato come [ richiede un argomento ] corrispondente). Vedi anche la pagina pitfalls qui, molti dei quali sono relativi a quel comando.

+1

+1, ma potresti voler aggiungere '-q' a' grep' per sopprimere l'output. – Sorpigal

1

Il piping in un'istruzione if è possibile con le subshell, ma tale soluzione si interromperà poiché si eseguono due comandi grep sulla pipe, il primo dei quali lo scaricherà.

La soluzione migliore nel tuo caso è probabilmente da leggere /etc/passwd in una variabile, allora si grep:

passwd=$(cat /etc/passwd) 
if (echo $passwd | grep -q root); then 
    echo "root found" 
fi 
if (echo $passwd | grep -q nobody); then 
    echo "nobody found" 
fi 
+0

È più economico dire "IFS = read -r -d" password Sorpigal

+0

Ok, ma non vedo come ciò garantisca un -1. –

+2

Non funziona. Non so chi l'abbia fatto, ma ho contro-votato in oltraggio. – Sorpigal

3

Io suggerirei usando awk:

cat /etc/passwd | awk '/root/{ do something }/nobody/{ do something else }' 

È possibile ottenere lo stesso in bash usando un'espressione come:

cat /etc/passwd | 
while read; do 
    if echo "$REPLY" | fgrep root; then 
    something 
    fi 
    if echo "$REPLY" | fgrep nobody; then 
    something_else 
    fi 
done 

Tuttavia ba puro La soluzione sh è meno efficiente per gli input di grandi dimensioni poiché esegue istanze separate di grep per ogni riga.

+0

Non utilizzare 'cat' come tale, puoi passare' passwd' direttamente a 'awk',' while', ecc. – Sorpigal

+1

Vero, ma è spesso più leggibile in questo modo perché l'origine dati è in prima fila, e per l'analisi di alcune dozzine di linee le prestazioni non sono un problema. A questa scala è solo una questione di preferenze personali e non una ragione per votare. –

0

Nel caso generale, è possibile utilizzare un file temporaneo.

t=$(mktemp -t passwd.XXXXXXXX) 
trap 'rm $t' 0 
trap 'exit 127' 1 2 3 5 15 
cat >$t 
for u in root nobody; do 
    fgrep $u $t 
done 

I trap s sono per rimuovere il file temporaneo dopo.

Per inciso, è possibile tubo ad un if, ma la prima grep all'interno della vostra condizione sarebbe già consumare tutto il suo standard input. E 'più utile in situazioni come questa:

if $option_count ; then 
    wc -l 
else 
    tac 
fi <file 
1

Basta usare & &:

grep -q root /etc/password && echo "root is found" 

grep -q nobody /etc/password && echo "nobody is found" 
0

Come circa i seguenti:

#!/bin/bash 

if [ -z $1 ]; then 
    echo Usage: $0 [UID to search for] 
    exit 1; 
fi 

SEARCHID="$1" 

function notFound() { 
    echo NOT FOUND 
} 

function found() { 
    echo Found it 
} 

function main() { 

    grep -i $SEARCHID /etc/passwd 
    # Move $? to a variable 
    SEARCHRESULT=$? 

    if [ "$SEARCHRESULT" != "0" ]; then 
     notFound; 
    else 
     found; 
    fi 
} 

# call main function 
main 
Problemi correlati