'grep' não funciona com 'time'?

'grep' não funciona com 'time'?

Por que time ls | grep realproduz isso

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

em vez de apenas

real    0m0.002s

Se eu digitar

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

Eu consigo o que espero, ou seja

real    0m0.002s

Eu descobri que isso funciona

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

O que esse comando faz?

Responder1

Por que time ls | grep realnão funciona como esperado.

timeé uma bashpalavra reservada e se comporta de maneira diferente de /usr/bin/time.

Se a palavra reservada de tempo preceder um pipeline, o tempo decorrido, bem como o tempo do usuário e do sistema consumido por sua execução serão relatadosquando o pipeline termina.

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

Além disso, timeas saídas para erro padrão e não para saída padrão.

Use o seguinte comando:

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

Notas:

  • O (e )agrupa os comandos timee ls(para que esses comandos sejam avaliados primeiro)

  • 2>&1 >/dev/nullprimeiro redireciona stderr para stdout (que é o canal) e depois redireciona stdout para /dev/null.

    Então stderr vai para o cano e stdout não leva a lugar nenhum.


Leitura adicional

Responder2

Sim, funciona, mas requer um pouco de redirecionamento de E/S :)

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

Saída :

real    0m1,003s

LerPerguntas frequentes sobre bash nº 32eTutorial de redirecionamento de E/S


Uma maneira bem mais simples:

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

Responder3

Duas questões aqui.

Primeiro e mais importante, "time" envia sua saída para stderr (erro padrão) e não para stdout, para que não seja capturado por comandos normais de redirecionamento, a menos que você tome medidas especiais.

Segundo, time não é um programa normal, mas um comando especial integrado interpretado diretamente pelo shell (para shells como bash, csh, tcsh, etc.). Portanto, ele funciona de maneira não padrão e cronometra todo o resto da linha de comando (a menos que você esteja usando um shell muito incomum).

Então, para obter o resultado desejado (usando bash), você precisa usar:

(time ls) 2>&1 | grep real

Isso executará o "ls" em um subshell e cronometrará [(tempo ls)] , envie o erro padrão para a saída padrão[2>&1]e, em seguida, envie o padrão para "grep" [|grep].

A última parte que você usou ">?dev/null" descarta a saída normal do próprio comando ls, caso inclua a palavra "real".

Responder4

Parece que timegrava diretamente no console e não em stdout, o que significa que a saída do comando ou pipeline não é afetada pela adição de time.

Portanto, grepnunca vê o relatório de tempo, que em qualquer caso é gerado após grepa conclusão, já que todo o pipeline é cronometrado.

informação relacionada