Asumiendo un grep simple como:
$ psa aux | grep someApp
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Esto proporciona mucha información, pero como falta la primera línea del comando ps no hay contexto para la información. Preferiría que también se muestre la primera línea de ps:
$ psa aux | someMagic someApp
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Por supuesto, podría agregar una expresión regular a grep específicamente para ps:
$ ps aux | grep -E "COMMAND|someApp"
Sin embargo, preferiría una solución más general ya que hay otros casos en los que me gustaría tener la primera línea también.
Parece que este sería un buen caso de uso para un descriptor de archivo "stdmeta" .
bash
command-line
dotancohen
fuente
fuente

ackson tan útiles, y porperlúltimo se dispararonsed,awk, etc en popularidad: es importante que las partes en suma en un todo coherente.-Cargumentopsay no necesitaría canalizarlo a grep. por ejemplo,ps u -C someAppo inclusops u -C app1 -C app2 -C app3ps aux | { head -1; grep foo; }mencionada por @Nahuel Fouilleul a continuación (la suya es probablemente la única solución que podría recordar en el acto si fuera necesario)Respuestas:
Buen camino
Normalmente no puede hacer esto con grep pero puede usar otras herramientas. AWK ya se mencionó, pero también puede usarlo
sedasí:Cómo funciona:
La utilidad Sed funciona en cada línea individualmente, ejecutando comandos específicos en cada una de ellas. Puede tener múltiples comandos, especificando varias
-eopciones. Podemos anteponer cada comando con un parámetro de rango que especifica si este comando debe aplicarse a una línea específica o no."1p" es un primer comando. Utiliza un
pcomando que normalmente imprime todas las líneas. Pero lo anteponemos con un valor numérico que especifica el rango al que debe aplicarse. Aquí, usamos lo1que significa primera línea. Si desea imprimir más líneas, puede usarx,ypdóndexestá la primera línea para imprimir,yes la última línea para imprimir. Por ejemplo, para imprimir las primeras 3 líneas, usaría1,3pEl siguiente comando es el
dque normalmente elimina todas las líneas del búfer. Antes de este comando ponemosyourpatternentre dos/caracteres. Esta es la otra forma (primero fue especificar en qué líneas como hicimos con elpcomando) de direccionar las líneas en las que el comando debería estar ejecutándose. Esto significa que el comando solo funcionará para las líneas que coincidenyourpattern. Excepto, usamos el!carácter antes deldcomando que invierte su lógica. Entonces ahora eliminará todas las líneas que no coinciden con el patrón especificado.Al final, sed imprimirá todas las líneas que quedan en el búfer. Pero eliminamos las líneas que no coinciden del búfer, por lo que solo se imprimirán las líneas coincidentes.
Para resumir: imprimimos la primera línea, luego eliminamos todas las líneas que no coinciden con nuestro patrón de la entrada. Resto de las líneas se imprimen (tan sólo las líneas que hacen coincidir con el patrón).
Problema de primera línea
Como se mencionó en los comentarios, hay un problema con este enfoque. Si el patrón especificado coincide también con la primera línea, se imprimirá dos veces (una por
pcomando y otra por una coincidencia). Podemos evitar esto de dos maneras:Agregar
1dcomando después1p. Como ya mencioné, eldcomando elimina líneas del búfer y especificamos su rango con el número 1, lo que significa que solo eliminará la primera línea. Entonces el comando seríased -e '1p' -e '1d' -e '/youpattern/!d'Usando el
1bcomando, en lugar de1p. Es un truco.bEl comando nos permite saltar a otro comando especificado por una etiqueta (de esta manera se pueden omitir algunos comandos). Pero si esta etiqueta no se especifica (como en nuestro ejemplo) simplemente salta al final de los comandos, ignorando el resto de los comandos para nuestra línea. Entonces, en nuestro caso, el últimodcomando no eliminará esta línea del búfer.Ejemplo completo:
Usando punto y coma
Algunas
sedimplementaciones pueden ahorrarle algo de tipeo usando punto y coma para separar comandos en lugar de usar múltiples-eopciones. Entonces, si no te importa ser portátil, el comando seríaps aux | sed '1b;/syslog/!d'. Funciona al menos enGNU sedebusyboximplementaciones.Manera loca
Aquí hay, sin embargo, una forma bastante loca de hacer esto con grep. Definitivamente no es óptimo, estoy publicando esto solo con fines de aprendizaje, pero puede usarlo, por ejemplo, si no tiene ninguna otra herramienta en su sistema:
Cómo funciona
Primero, usamos la
-nopción para agregar números de línea antes de cada línea. Queremos numerar todas las líneas que estamos haciendo coincidir.*, cualquier cosa, incluso una línea vacía. Como se sugiere en los comentarios, también podemos hacer coincidir '^', el resultado es el mismo.Luego estamos usando expresiones regulares extendidas para que podamos usar
\|caracteres especiales que funcionen como OR. Entonces, hacemos coincidir si la línea comienza con1:(primera línea) o contiene nuestro patrón (en este caso, susyslog).Problema de números de línea
Ahora el problema es que estamos obteniendo estos números de línea feos en nuestra salida. Si esto es un problema, podemos eliminarlos de
cutesta manera:-dLa opción especifica delimitador,-fespecifica los campos (o columnas) que queremos imprimir. Por lo tanto, queremos cortar cada línea en cada:carácter e imprimir solo la segunda y todas las columnas posteriores. Esto elimina efectivamente la primera columna con su delimitador y esto es exactamente lo que necesitamos.fuente
cat -ny se vería más clara como con un grep abusado por esto.nlno cuenta líneas vacías (pero las imprime sin número de línea),cat -nformatea la numeración con espacios anteriores,grep -n .elimina las líneas vacías y agrega dos puntos. Todos tienen sus ... er ... características ;-)ps aux | sed '1p;/pattern/!d'imprimirá la primera línea dos veces si coincide con el patrón . Lo mejor es utilizado elbcomando:ps aux | sed -e 1b -e '/pattern/!d'.cat -nNo es POSIX.grep -n '^'numeraría cada línea (no es un problema para la salida ps que no tiene líneas vacías).nl -ba -d $'\n'numera cada línea.1b;...no es portátil ni POSIX, no puede haber ningún otro comando después de "b", por lo que necesita una nueva línea u otra expresión -e.¿Cómo te sientes acerca de usar en
awklugar degrep?NR == 1: Número de registro == 1; es decir. la primera linea||: o:/syslogd/: Patrón para buscarTambién podría valer la pena mirarlo
pgrep, aunque esto es más para los scripts que para la salida orientada al usuario. Sin embargo, evita que elgrepcomando en sí aparezca en la salida.fuente
EDITAR: después de los comentarios
Pensé
head -1que leería todas las entradas, pero después de probarlo, también funciona.la salida es
fuente
{ IFS='' read line; ... }en caso de que el encabezado comience con espacios.head -1lugar del combo de lectura / eco.head -n1en mi fiesta. Esto probablemente puede ser específico de la implementación. Mi cabeza no está leyendo toda la entrada en este caso, solo la primera línea, dejando el resto en el búfer de entrada.head -n1es más corto, pero parece que incluso la especificación POSIX no dice cuánto de su entrada puede leer, por lo que quizásread line; echo $linesea más portátil después de todo.Ps admite filtro interno,
Supongamos que está buscando un proceso bash:
ps -C bash -fEnumerará todos los procesos que nombraron
bash.fuente
Tiendo a enviar el encabezado a stderr :
Esto suele ser suficiente para fines de lectura humana. p.ej:
La parte entre corchetes podría ir en su propio guión para uso general.
Hay una conveniencia adicional en que la salida se puede canalizar más (a
sortetc.) y el encabezado permanecerá en la parte superior.fuente
También puedes usar
teeyhead:Sin embargo,
teetenga en cuenta que, mientras no pueda ignorar lasSIGPIPEseñales (ver, por ejemplo, la discusión aquí ), este enfoque necesita una solución alternativa para ser confiable. La solución alternativa es ignorar las señales SIGPIPE, esto se puede hacer, por ejemplo, en bash como shells:También tenga en cuenta que el orden de salida no está garantizado .
fuente
grep:| { sleep .5; cat }.Quizás dos
pscomandos serían los más fáciles.fuente
ps auxllamada ... Y si solo quieres esa primera línea estática, ¿por qué no repetirla manualmente?Podrías usar pidstat con:
Ejemplo:
Más información: http://linux.die.net/man/1/pidstat
fuente
Ponga lo siguiente en su archivo .bashrc o copie / pegue en el shell primero, para probar.
Uso: psls [patrón grep]
Asegúrese de obtener su .bashrc (o .bash_profile si lo coloca allí):
La función incluso se completará automáticamente en la línea de comandos del shell. Como indicó en otra respuesta, puede canalizar la primera línea a un archivo para guardar una llamada a ps.
fuente
psl, que solo llamapsygrepuna vez cada una (y no necesitahead).ordenar pero mantener la línea de encabezado en la parte superior
Y úsalo así
fuente
Gracias principalmente a Janis Papanagnou en comp.unix.shell, uso la siguiente función:
Esto tiene una serie de ventajas:
-ipara coincidencias que no distingan entre mayúsculas y minúsculas,-Epara expresiones regulares extendidas, etc.Ejemplo de uso:
fuente
Otra forma con
gnu ed:o, si el shell admite la sustitución del proceso:
es decir:
Más portátil, sin
gnu'!'sustitución de shell, utilizando solo eledincorporadorpararenviar la salidaps auxal búfer y luego eliminar las líneas que no coinciden en el2,$rango e imprimir el resultado:Y dado que los
sedcomandos en la respuesta aceptada también muestran la línea que coinciden, con unasedque admite-f-y una shell que admite la sustitución de procesos, ejecutaría:que prácticamente hace lo mismo que los
edcomandos anteriores .fuente
El camino de Perl:
Mucho más fácil de leer que
sed, más rápido, sin riesgo de elegir líneas no deseadas.fuente
Si eso es solo para procesos grepping con encabezados completos, expandiría la sugerencia de @ mrb:
pgrep bash | xargs ps -fpobtendrá el mismo resultado pero sin una subshell. Si se requiere otro formato:fuente
Si conoce los números de línea exactos, ¡es fácil con perl! Si desea obtener las líneas 1 y 5 de un archivo, diga / etc / passwd:
Si desea obtener otras líneas también, simplemente agregue sus números en la matriz.
fuente