為什麼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
筆記:
(
和將和命令)
組合在一起(因此這些命令首先被評估)time
ls
2>&1 >/dev/null
首先將 stderr 重定向到 stdout (即管道),然後將 stdout 重定向到/dev/null
.所以 stderr 進入管道,而 stdout 則無處可去。
進一步閱讀
- Linux Bash 命令列的 AZ 索引- 與 Bash 命令列相關的所有內容的絕佳參考。
- 括號- 使用括號對表達式進行分組和擴展。
- 語法重定向- 重定向和進程替換。
- Bash 參考手冊:重定向
- 圖解重定向教學 [Bash Hackers Wiki]
答案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
一個相當簡單的方法:
$ 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
完成後產生的,因為整個管道都是定時的。