Una manera fácil es agregar un pase de tr
para exprimir cualquier separador de campo repetido:
$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4
Tenga en cuenta que el tr -s ' '
La opción no eliminará ningún espacio inicial único. Si su columna está alineada a la derecha (como con ps
pid)...
$ ps h -o pid,user -C ssh,sshd | tr -s " "
1543 root
19645 root
19731 root
Luego, cortar dará como resultado una línea en blanco para algunos de esos campos si es la primera columna:
$ <previous command> | cut -d ' ' -f1
19645
19731
A menos que lo preceda con un espacio, obviamente
$ <command> | sed -e "s/.*/ &/" | tr -s " "
Ahora, para este caso particular de números pid (no nombres), hay una función llamada pgrep
:
$ pgrep ssh
Funciones de shell
Sin embargo, en general, todavía es posible usar funciones de shell de manera concisa, porque hay algo interesante sobre el read
comando:
$ <command> | while read a b; do echo $a; done
El primer parámetro para leer, a
, selecciona la primera columna, y si hay más, todo lo demás se pondrá en b
. Como resultado, nunca necesitará más variables que el número de su columna +1 .
Entonces,
while read a b c d; do echo $c; done
luego generará la tercera columna. Como se indica en mi comentario...
Se ejecutará una lectura canalizada en un entorno que no pasa variables al script de llamada.
out=$(ps whatever | { read a b c d; echo $c; })
arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]} # will output 'b'`
La solución de matriz
Entonces terminamos con la respuesta de @frayser, que es usar la variable de shell IFS, que por defecto es un espacio, para dividir la cadena en una matriz. Sin embargo, solo funciona en Bash. Dash y Ash no lo apoyan. Me ha costado mucho dividir una cadena en componentes en una cosa Busybox. Es bastante fácil obtener un solo componente (por ejemplo, usando awk) y luego repetirlo para cada parámetro que necesite. Pero luego termina llamando repetidamente a awk en la misma línea, o usando repetidamente un bloque de lectura con eco en la misma línea. Lo cual no es eficiente ni bonito. Entonces terminas dividiendo usando ${name%% *}
y así. Te hace anhelar algunas habilidades de Python porque, de hecho, los scripts de shell ya no son muy divertidos si la mitad o más de las funciones a las que estás acostumbrado desaparecen. Pero puede suponer que ni siquiera python estaría instalado en dicho sistema, y no lo estaba;-).
Creo que la forma más sencilla es usar awk . Ejemplo:
$ echo "11383 pts/1 00:00:00 bash" | awk '{ print $4; }'
bash