Buen camino
Normalmente no puede hacer esto con grep pero puede usar otras herramientas. AWK ya se mencionó, pero también puede usarlo sed
así:
sed -e '1p' -e '/youpattern/!d'
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 -e
opciones. 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 p
comando 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 lo 1
que significa primera línea. Si desea imprimir más líneas, puede usar x,yp
dónde x
está la primera línea para imprimir, y
es la última línea para imprimir. Por ejemplo, para imprimir las primeras 3 líneas, usaría1,3p
El siguiente comando es el d
que normalmente elimina todas las líneas del búfer. Antes de este comando ponemos yourpattern
entre dos /
caracteres. Esta es la otra forma (primero fue especificar en qué líneas como hicimos con el p
comando) 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 coinciden yourpattern
. Excepto, usamos el !
carácter antes del d
comando 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 p
comando y otra por una coincidencia). Podemos evitar esto de dos maneras:
Agregar 1d
comando después 1p
. Como ya mencioné, el d
comando 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 1b
comando, en lugar de 1p
. Es un truco. b
El 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 último d
comando no eliminará esta línea del búfer.
Ejemplo completo:
ps aux | sed -e '1b' -e '/syslog/!d'
Usando punto y coma
Algunas sed
implementaciones pueden ahorrarle algo de tipeo usando punto y coma para separar comandos en lugar de usar múltiples -e
opciones. Entonces, si no te importa ser portátil, el comando sería ps aux | sed '1b;/syslog/!d'
. Funciona al menos en GNU sed
e busybox
implementaciones.
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:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Cómo funciona
Primero, usamos la -n
opció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 con 1:
(primera línea) o contiene nuestro patrón (en este caso, su syslog
).
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 cut
esta manera:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
La opción especifica delimitador, -f
especifica 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.
ack
son tan útiles, y porperl
último se dispararonsed
,awk
, etc en popularidad: es importante que las partes en suma en un todo coherente.