Considere el siguiente archivo de entrada:
1
2
3
4
Corriendo
{ grep -q 2; cat; } < infile
no imprime nada Esperaría que se imprima
3
4
Puedo obtener el resultado esperado si lo cambio a
{ sed -n 2q; cat; } < infile
¿Por qué el primer comando no imprime el resultado esperado?
Es un archivo de entrada que se puede buscar y según el estándar en OPCIONES :
-q
Quiet. Nothing shall be written to the standard output, regardless of
matching lines. Exit with zero status if an input line is selected.
y más abajo, bajo USO DE LA APLICACIÓN (enfatizar el mío):
La
-q
opción proporciona un medio para determinar fácilmente si existe o no un patrón (o cadena) en un grupo de archivos. Al buscar varios archivos, proporciona una mejora en el rendimiento ( porque puede salir tan pronto como encuentra la primera coincidencia ) [...]
Ahora, según el mismo estándar (en Introducción , en ARCHIVOS DE ENTRADA )
Cuando una utilidad estándar lee un archivo de entrada que se puede buscar y finaliza sin un error antes de que llegue al final del archivo, la utilidad se asegurará de que el desplazamiento del archivo en la descripción del archivo abierto se coloque correctamente justo después del último byte procesado por la utilidad [. ..]
tail -n +2 file
(sed -n 1q; cat) < file
...
El segundo comando es equivalente al primero solo cuando el archivo es buscable.
¿Por qué grep -q
consume todo el archivo?
Esto es gnu grep
si importa (aunque Kusalananda acaba de confirmar que sucede lo mismo en OpenBSD)
grep
es una bifurcación de algo llamado FreeGrep , si alguien se lo pregunta.Respuestas:
grep
se detiene temprano, pero amortigua su entrada por lo que su prueba es demasiado corta (y sí, me doy cuenta de que mi prueba es imperfecta ya que no se puede buscar):comienza en 6776 en mi sistema. Eso coincide con el búfer de 32 KB utilizado por defecto en GNU grep:
salidas
Tenga en cuenta que POSIX solo menciona mejoras de rendimiento
Eso no establece expectativas para las mejoras de rendimiento debido a la lectura parcial de un solo archivo.
fuente
Obviamente, esto se debe al almacenamiento en búfer que
grep
acelera las cosas. Hay herramientas que están específicamente diseñadas para leer tantos caracteres como se solicite y no más. Uno de ellos esexpect
:No tengo un sistema para probar esto, pero creo que
expect
se comerá todo hasta que encuentre la cadena esperada (2
), y luego termine, dejando el resto de la entrada paracat
.fuente
Estás confundiendo sed y grep.
Para el comando sed,
-2q
se dice que salga de la iteración actual si en la segunda línea, la-n
opción dice que funcione de manera silenciosa, por lo que obtendrá todas las líneas después de la segunda.El comando grep se ejecuta de manera predeterminada para generar todas las líneas coincidentes, pero la
-q
opción dice no generar nada en stdout. entonces, si la entrada contiene un "2", tendrá un valor de salida de ÉXITO, de lo contrario FALLA. Cuáles son esos depende de su sistema operativo y shell. Por lo tanto, normalmente diría si una línea coincide al examinar el valor de salida del proceso grep. Esto es útil en una tubería donde desea saber si su entrada contiene algún valor como prueba. P.ejEn este caso, realmente no nos importa ver todas las líneas coincidentes, solo nos importa si existe al menos una. El
report_crash_via_email
proceso / función puede luego apagarse y volver a abrir el archivo, o no.Si desea que su proceso grep se DETENGA después de encontrar el carácter "2", no lo hará de manera predeterminada, inspeccionará cada línea para ver si coincide, debe decirle que lo haga. El cambio de línea de comando para eso es
-m <value>
. Entonces para su casogrep -q -m1 2
,.fuente
grep
pero esta pregunta es sobre algo más sutil y esotérico. Parece que has leído la pregunta demasiado rápido para entender el comportamiento real que se está consultando. Además, GNUgrep
hace la búsqueda de parada cuando se utiliza con-q
(según lo permitido en la cita de la especificación POSIX): La página del manual para los estados de GNU grep que “Salir [S] inmediatamente con el estado cero si un partido se encontró” . FWIW, he editado tu pregunta para mostrar cómo puedes formatear publicaciones futuras. Bienvenido a Stack Exchange .grep
se le pregunta si existe '2' en el archivo, nada más y nada menos. No se comporta comosed
y consume registros hasta ese punto y deja el resto para su posterior procesamiento. Se lee hasta que sabe que hay un '2' o que no existe, cierra el archivo y devuelve el resultado.grep
de hecho, solo "consume todo el archivo" (ignorando las consideraciones de almacenamiento en búfer) si la cadena de búsqueda no está presente en el archivo (lo cual se puede probar solo examinando todo el archivo). Cualquier cosa menos que eso, la lectura del archivo se detiene , el archivo se cierra y el ÉXITO regresó.