如果我有一些輸入,是在運行操作之前過濾資料更好awk
還是應該在 中進行所有過濾awk
?
例如,給出以下輸入:
$ echo "foo\nbar\nbaz"
foo
bar
baz
我應該運行:
$ echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo cats
或者:
$ echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo cats
- 我為什麼要運行其中任何一個?
- 我應該使用不同的工具嗎?
- 我應該考慮哪些因素?
- 我該如何測試這些因素?
答案1
在這種特定情況下,第二種選擇是更好的選擇。
一般來說,盡量減少管道中公用設施的數量會更有效。最好不要分叉(啟動)不必要的進程(如第一個範例中的不必要sed
進程)。在網路上,不難找到投訴的例子貓的無用用途。
對於大多數現代類 Unix 系統*,分叉的執行非常有效,但這取決於正在啟動的進程的大小,例如,啟動perl
orpython
會比sed
or慢得多awk
。
對於一次性命令,這並不重要 - 但如果您的管道位於循環內並多次運行,從管道中刪除不必要的進程可以顯著加快總執行時間。
具體問題
我為什麼要運行其中任何一個?
如果您比另一種更熟悉其中一種的語法,那麼使用您最熟悉的工具/語言可能會更好地提高程式碼的可讀性(和可維護性)。
我應該使用不同的工具嗎?
在這種具體情況下,我不這麼認為。和awk
都是sed
適合這類工作的工具。
我應該考慮哪些因素?
如果您必須處理多個文件(例如,在循環中),那麼速度/效率將很重要。
如果您只是經常處理一個大文件,那麼程式碼的可讀性可能更重要。
我該如何測試這些因素?
您可以使用該time
實用程式來分析不同的版本,該實用程式可作為 Bash 內建的 shell 使用,也可作為獨立的可執行程式使用。例如,執行兩個範例命令顯示第一個範例比第二個範例花費了 0.012 秒的時間。
$ time echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.056s
user 0m0.000s
sys 0m0.045s
$ time echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.044s
user 0m0.000s
sys 0m0.031s
請注意,分析基準受到系統負載和其他限制因素的影響,因此您需要多次重複此操作才能真實了解哪個版本比另一個版本更快。
*對於 MS Windows,分叉是成本更高,因此在 Cygwin 等環境中運行時,最小化啟動的進程數量確實會產生影響。
答案2
用起來就夠了awk(或者sed)用於此類簡單情況的工具。多個工具的組合會過於複雜且通常是多餘的:
echo -e "foo\nbar\nbaz" | awk 'NR==1{print $0" cats"}'
輸出:
foo cats
我應該考慮哪些因素?
確保所需的文字處理需要組合幾種不同的工具,否則 - 使用不同工具的功能
假設我只需要在輸入字串中的第一個單字之前添加某個單字 - 這也很容易sed工具:
echo -e "foo\nbar\nbaz" | sed 's/^.*$/& cats/; 1q'
foo cats
echo -e
,e
標誌“啟用反斜線轉義的解釋”
無論如何,這取決於您的輸入文字有多複雜以及您的文字處理規則有多複雜