「grep」不適用於「時間」?

「grep」不適用於「時間」?

為什麼time ls | grep real輸出這個

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

而不是僅僅

real    0m0.002s

如果我輸入

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

我得到了我所期望的,即

real    0m0.002s

我發現這有效

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

這個指令有什麼作用?

答案1

為什麼沒有time ls | grep real如預期工作。

time是一個bash保留字,其行為與 不同/usr/bin/time

如果時間保留字位於管道之前,則會報告其執行所消耗的時間以及使用者和系統時間當管道終止時

來源bash(1):GNU Bourne-Again SHell - Linux 手冊頁

此外,time輸出到標準誤差而不是標準輸出。

使用以下命令:

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

筆記:

  • (和將和命令)組合在一起(因此這些命令首先被評估)timels

  • 2>&1 >/dev/null首先將 stderr 重定向到 stdout (即管道),然後將 stdout 重定向到/dev/null.

    所以 stderr 進入管道,而 stdout 則無處可去。


進一步閱讀

答案2

是的,它可以工作,但它需要一些 I/O 重定向:)

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

輸出 :

real    0m1,003s

bash 常見問題#32I/O 重定向教程


一個相當簡單的方法:

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

答案3

這裡有兩個問題。

首先也是最重要的是,「時間」將其輸出發送到 stderr(標準錯誤)而不是 stdout,這樣除非您採取特殊措施,否則它不會被正常的重定向命令捕獲。

其次,time 不是普通的程序,而是由 shell 直接解釋的特殊內建指令(對於 bash、csh、tcsh 等 shell)。因此,它以非標準方式工作,並且對命令列的整個其餘部分進行計時(除非您使用的是非常不尋常的 shell)。

因此,要獲得您想要的結果(使用 bash),您需要使用:

(time ls) 2>&1 | grep real

這將在子 shell 中運行“ls”併計時 [(時間ls)] ,將標準錯誤傳送至標準輸出[ 2>&1 ],然後將標準送到“grep”[|grep]。

您使用的最後一部分 ">?dev/null" 會丟棄 ls 指令本身的正常輸出,以防其中包含單字「real」。

答案4

看起來time直接寫入控制台而不是寫入stdout,這意味著命令或管道的輸出不會受到添加的影響time

因此grep永遠不會看到時間報告,該報告在任何情況下都是在grep完成後產生的,因為整個管道都是定時的。

相關內容