Shell

ksh93怎麼這麼快?

  • December 22, 2014

所以,一般來說,我傾向於尋找sed文本處理——尤其是對於大文件——並且通常避免在 shell 本身中做這些事情。

不過,我認為這可能會改變。我正在四處尋找man ksh,我注意到了這一點:

<#pattern     Seeks forward to the beginning of the
             next line containing pattern.

<##pattern    The same as <# except that  the  por‐
             tion  of  the file that is skipped is
             copied to standard output.

對現實世界的實用性持懷疑態度,我決定嘗試一下。我做了:

seq -s'foo bar
' 1000000 >file

…對於一百萬行數據,如下所示:

1foo bar
...
999999foo bar
1000000

…並與之對抗sed

p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"    
do </tmp/file eval "time ( $c )"
done | wc -l

所以這兩個命令都應該達到999999foo bar並且它們的模式匹配實現必須至少評估每行的開頭和結尾才能這樣做。他們還必須針對否定模式驗證第一個字元。這是一件簡單的事情,但是……結果不是我所期望的:

( sed '/^[^0-8]99999.*bar/q' ) \
   0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
   0.02s user 0.01s system 91% cpu 0.033 total
1999997

ksh這裡使用 ERE 和sedBRE。我之前用和 shell 模式做了同樣的事情,ksh但結果並沒有什麼不同。

無論如何,這是一個相當大的差異 -ksh超過sed10 倍。我之前讀過 David Korn 編寫了他自己的 io lib 並在其中實現了它ksh——這可能是相關的嗎?- 但我對此幾乎一無所知。shell 是如何做到這一點的?

對我來說更令人驚訝的是,它ksh確實在你要求的地方留下了它的偏移量。要從*(GNU)中獲得**(幾乎)*相同的效果,您必須使用-very slowsed``-u

這是一個grepksh測試:

1000000         #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
   0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar   #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; )  \
   0.02s user 0.00s system 73% cpu 0.023 total

ksh在這裡節拍grep- 但並不總是 - 他們幾乎並列。儘管如此,這還是非常棒的,並且 ksh提供了前瞻 -head的輸入在匹配之前開始。

我想,這似乎好得令人難以置信。這些命令在幕後有什麼不同?

哦,顯然這裡甚至沒有子shell:

ksh -c 'printf %.5s "${<file;}"'

ksh 不僅使用sfio,而且使用自己的自定義記憶體分配器。

儘管如此,我的猜測是 sfio 在這種情況下有所作為。我只是嘗試在 strace 下執行您的範例,可以看到 ksh 呼叫讀/寫約 200 次(65 KB 塊),而 sed 呼叫約 3400 次(4 KB 塊)。使用 sed -u 我的筆記型電腦幾乎融化了,讀取按字節完成,按行寫入。Ksh simple 使用 lseek。Grep 使用讀取約 400 次(32 KB 塊)。

引用自:https://unix.stackexchange.com/questions/175378