GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo puedo recorrer la salida de un comando de shell?

Descubrí que puedes hacer esto simplemente usa comillas dobles:

while read -r proc; do
     #do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"

Esto guardará cada línea en la matriz en lugar de cada elemento.


Nunca for Repita los resultados de un comando de shell si desea procesarlo línea por línea a menos que esté cambiando el valor del separador de campo interno $IFS a \n . Esto se debe a que las líneas estarán sujetas a división de palabras lo que conduce a los resultados reales que está viendo. Es decir, si, por ejemplo, tiene un archivo como este:

foo bar
hello world

El siguiente bucle for

for i in $(cat file); do
    echo "$i"
done

te da:

foo
bar
hello
world

Incluso si usas IFS='\n' las líneas aún pueden estar sujetas a expansión de nombre de archivo

Recomiendo usar while + read en cambio porque read lee línea por línea.

Además, usaría pgrep si está buscando pids pertenecientes a un determinado binario. Sin embargo, dado que python puede aparecer como binarios diferentes, como python2.7 o python3.4 Sugiero pasar -f al pgrep lo que hace que busque en toda la línea de comando en lugar de solo buscar binarios llamados python . Pero esto también encontrará procesos que se han iniciado como cat foo.py . ¡Usted ha sido advertido! Al final, puede refinar la expresión regular pasada a pgrep como desees.

Ejemplo:

pgrep -f python | while read -r pid ; do
    echo "$pid"
done

o si también quieres el nombre del proceso:

pgrep -af python | while read -r line ; do
    echo "$line"
done

Si desea el nombre del proceso y el pid en variables separadas:

pgrep -af python | while read -r pid cmd ; do
    echo "pid: $pid, cmd: $cmd"
done

Ya ves, read ofrece una forma flexible y estable de procesar la salida de un comando línea por línea.

Por cierto, si prefieres tu ps .. | grep línea de comando sobre pgrep usa el siguiente bucle:

ps -ewo pid,etime,cmd | grep python | grep -v grep | grep -v sh \
  | while read -r pid etime cmd ; do
    echo "$pid $cmd $etime"
done

Observe cómo cambié el orden de etime y cmd . Así poder leer cmd , que puede contener espacios en blanco, en una sola variable. Esto funciona porque read dividirá la línea en variables, tantas veces como haya especificado las variables. La parte restante de la línea, posiblemente incluidos los espacios en blanco, se asignará a la última variable que se haya especificado en la línea de comando.


Al usar for bucles en bash divide la lista dada por defecto por whitespaces , esto se puede adaptar usando el llamado Separador de campo interno o IFS en resumen.

IFS El separador de campo interno que se usa para dividir palabras después de la expansión y para dividir líneas en palabras con el comando integrado de lectura. El valor predeterminado es "".

Para su ejemplo, tendríamos que decirle a IFS usar new-lines como punto de quiebre.

IFS=$'\n'

for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)
do
   echo $tbl
done

Este ejemplo devuelve el siguiente resultado en mi máquina.

  668 /usr/bin/python /usr/bin/ud    03:05:54
27892 python                            00:01

Linux
  1. ¿Cómo asignar la salida de un comando a una variable de shell?

  2. ¿Cómo resaltar una palabra en la salida de "gato"?

  3. ¿Cuál es la diferencia de obtener salida de comando usando `command` y $(command) en Shell?

  4. ¿Cómo capturar la salida de un comando superior en un archivo en Linux?

  5. ¿Cómo usar el comando su sobre adb shell?

Cómo usar el comando grep de Linux

Cómo ejecutar comandos de Shell a través del servidor HTTP

Cómo redirigir la salida del comando de shell

¿Cómo puedo copiar la salida de un comando remoto en el portapapeles local?

¿Cómo puedo ocultar la salida de una aplicación de shell en Linux?

¿Cómo leer la columna IDLE en la salida del comando Linux 'w'?