2012-02-24 24 views
10

Tengo un script que genera alrededor de 10 líneas cada vez que se ejecuta. El contenido de estas líneas varía.¿Posible canalizar en una instrucción if?

Realmente me gustaría poder grep en la salida y hacer diferentes cosas dependiendo de la salida.

En seudo esto es lo que me gustaría hacer

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

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

fi 

Aquí he utilizado cat /etc/password como un ejemplo, pero debe ser reemplazado con mis guiones mencionados anteriormente.

El problema es, ¿cómo puedo obtener la salida de cat /etc/password en las condiciones if/elif?

+1

Tal awk o perl son más adecuados para su tarea .. – bew

+2

no use 'cat' si la intención no es mostrar o concatenar. Aquí puede simplemente dar el archivo en la línea de comando grep, porque es aceptado, de lo contrario puede redirigir el archivo ('<'). – Benoit

+2

No necesita continuación de línea después de '|', '&&' y '||' –

Respuesta

5

Como @Benoit recomienda, solo use grep directamente.

Como señala @larsmans, puede evitar una lectura doble del archivo leyéndola en una variable una vez.

dada la disponibilidad de bash lo haría así:

password=$(< /etc/passwd) 

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

Una lectura del archivo, una o dos invocaciones de grep, no hay otros procesos o subniveles lanzados.

+0

Solución muy interesante. ¿Por qué tienes 'IFS =' en la primera línea? –

+2

En bash, puedes simplemente decir 'password = $ (

+0

Un buen punto glenn, lo había olvidado. – Sorpigal

3

que acaba de hacer:

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

que jugará los comandos ... si el código de salida de grep es 0.

recordar que \[ is a external command, probablemente situado en /usr/bin/[ (normalmente se trata de un enlace duro a test y cuando invocado como [ requiere un argumento ] coincidente). También vea la página pitfalls aquí, muchos de ellos se relacionan con ese comando.

+1

+1, pero es posible que desee agregar '-q' a' grep' para suprimir la salida. – Sorpigal

1

La canalización en una declaración if es posible con subcapas, pero esa solución se romperá ya que está ejecutando dos comandos grep en la tubería, el primero de los cuales lo agotará.

La mejor solución en su caso es probable que leer /etc/passwd en una variable, entonces se 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

Es más barato decir 'IFS = read -r -d '' contraseña Sorpigal

+0

Ok, pero no veo cómo eso garantiza un -1. –

+2

No es así. No sé quién hizo eso, pero contraataqué indignado. – Sorpigal

3

me gustaría sugerir el uso de awk:

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

Puede lograr lo mismo en bash usando una expresión como:

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

Sin embargo, la pure ba La solución sh es menos eficiente para entradas grandes porque ejecuta instancias separadas de grep para cada línea.

+0

No use 'cat' así, puede pasar' passwd' directamente a 'awk',' while', etc. – Sorpigal

+1

Cierto, pero a menudo es más legible de esta manera porque la fuente de datos está al frente, y para analizar unas pocas docenas de líneas, el rendimiento realmente no es un problema. En esta escala, es solo una cuestión de preferencia personal y no una razón para rechazarla. –

0

En el caso general, puede usar un archivo temporal.

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 

Los trap s son eliminar el archivo temporal después.

Como acotación al margen, se puede tubería a una if, pero la primera grep dentro de su condicional sería ya consumir la totalidad de su entrada estándar. Es más útil en situaciones como esta:

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

sólo tiene que utilizar & &:

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

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

¿Qué hay de los siguientes:

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