¿'grep' no funciona con 'tiempo'?

¿'grep' no funciona con 'tiempo'?

¿Por qué time ls | grep realsale esto?

real    0m0.002s
user    0m0.000s
sys     0m0.002s

en lugar de solo

real    0m0.002s

si escribo

echo -e 'real\t0m0.002s\nuser\t0m0.000s\nsys\t0m0.002s\n' | grep real

Obtengo lo que espero, es decir

real    0m0.002s

Descubrí que esto funciona

(time ls)  2>&1 > /dev/null | grep real

¿Qué hace este comando?

Respuesta1

¿Por qué time ls | grep realno funciona como se esperaba?

timees una bashpalabra reservada y se comporta de manera diferente a /usr/bin/time.

Si la palabra de tiempo reservado precede a una canalización, se informa el tiempo transcurrido, así como el tiempo consumido por el usuario y el sistema en su ejecución.cuando termina el oleoducto.

Fuentebash(1): GNU Bourne-Again SHell - página de manual de Linux

Además, timelas salidas son de error estándar, no de salida estándar.

Utilice el siguiente comando:

(time ls) 2>&1 >/dev/null | grep real 

Notas:

  • El (y )agrupa los comandos timey ls(para que estos comandos se evalúen primero)

  • 2>&1 >/dev/nullprimero redirige stderr a stdout (que es la tubería) y luego redirige stdout a /dev/null.

    Entonces stderr va a la tubería y stdout no va a ninguna parte.


Otras lecturas

Respuesta2

Sí, funciona, pero requiere un poco de redirección de E/S :)

$ exec 3>&1 4>&2
{ time sleep 1 1>&3 2>&4; } 2>&1 |
    grep 'real'    
exec 3>&- 4>&-

Producción :

real    0m1,003s

LeerPreguntas frecuentes sobre bash n.º 32yTutorial de redirección de E/S


Una forma bastante más sencilla:

$ TIMEFORMAT=%R
$ time sleep 1
1,003

Respuesta3

Dos cuestiones aquí.

Primero y más importante, "time" envía su salida a stderr (error estándar), no a stdout, para que no sea capturada por los comandos de redirección normales a menos que tome medidas especiales.

En segundo lugar, el tiempo no es un programa normal sino un comando especial incorporado interpretado directamente por el shell (para shells como bash, csh, tcsh, etc.). Por lo tanto, funciona de una manera no estándar y multiplica el resto de la línea de comandos (a menos que esté utilizando un shell muy inusual).

Entonces, para obtener el resultado que deseas (usando bash), necesitas usar:

(time ls) 2>&1 | grep real

Esto ejecutará "ls" en una subcapa y cronometrárálo [(tiempo ls)], envía el error estándar a la salida estándar[ 2>&1 ]y luego envía el estándar a "grep" [|grep].

La última parte que usó ">?dev/null" descarta la salida normal del comando ls en sí, en caso de que incluya la palabra "real".

Respuesta4

Parece que timeescribe directamente en la consola y no en stdout, lo que significa que la salida del comando o canalización no se ve afectada al agregar time.

Por lo tanto, grepnunca ve el informe de tiempo, que en cualquier caso se genera después de que grepse completa, ya que todo el proceso está cronometrado.

información relacionada