欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
perl在編輯巨大文件時(shí)的應用

perl在編輯巨大文件時(shí)的應用

日期:[2006-07-26] 人氣:[51] 評論:[0]條 字體:[ ] 得分:[0.00]

在實(shí)際中我們經(jīng)常需要處理一些非常大的文件,這時(shí)會(huì )有兩個(gè)問(wèn)題我們比較關(guān)注:一個(gè)是處理程序的性能,希望越快越好;另一個(gè)就是空間的占用問(wèn)題,不希望產(chǎn)生中間的文件,尤其是在有些空間非常緊張的磁盤(pán)上。

關(guān)于性能,通常用C編寫(xiě)的程序性能較高,這是顯然的,在此我們暫不討論。實(shí)際上一個(gè)編寫(xiě)良好的shell腳本往往能用可以接受的性能簡(jiǎn)單地完成任務(wù)。對于不太復雜的處理腳本甚至可以寫(xiě)在一行上,調試起來(lái)非常方便。相比之下,相應的C程序就有點(diǎn)“殺雞用牛刀”的感覺(jué)。我并不想挑起另一場(chǎng)Language War,我絕對承認:C的執行效率更高;這里只是想說(shuō)明:對于一些簡(jiǎn)單的問(wèn)題,shell的“開(kāi)發(fā)效率”要更高一些。

另外一個(gè)焦點(diǎn)就是空間占用問(wèn)題,如果能不產(chǎn)生臨時(shí)或者中間文件的話(huà)就比較理想。
大多數shell工具程序都具有相同的特點(diǎn),可以從標準輸入讀取輸入,并把結果寫(xiě)到標準輸出,這一特點(diǎn)非常好,使我們用管道連接多個(gè)工具完成一個(gè)相對復雜的任務(wù)成為可能。但這樣做勢必要生成中間文件,例如:
grep pattern file > tmpfile
mv tmpfile file
在小文件時(shí)這樣做沒(méi)多大關(guān)系,開(kāi)銷(xiāo)不會(huì )很大。但如果文件非常大的話(huà)有時(shí)就難以忍受了。
好在最新版本的GNU sed已經(jīng)支持-i選項,直接編輯原文件(只是在用戶(hù)表面看來(lái)如此:-(,下面會(huì )討論),只要這樣就行了:
sed -i ‘/pattern/!d‘ file
情況似乎很完美了,沒(méi)有中間文件,沒(méi)有額外的空間開(kāi)銷(xiāo),問(wèn)題解決!但是稍等,真的如此嗎?一個(gè)不可就藥的懷疑論者總會(huì )對此疑慮重重。^_^OK,我們來(lái)測試一下:

刪除一個(gè)文件的前10行,測試環(huán)境:P4 Xeon X2, 內存1G,10000轉SCSI磁盤(pán),CentOS 4.2 x86_64。GNU sed 4.1.2, Perl 5.8.5。

# seq 10000 >file1
# sed -i ‘1,10d‘p file1|lsof -c sed
COMMAND   PID USER   FD   TYPE DEVICE     SIZE    NODE NAME
sed     14855 root  cwd    DIR  253,0     4096 5357570 /home/user1
sed     14855 root  rtd    DIR  253,0     4096       2 /
sed     14855 root  txt    REG  253,0    52904 6012986 /bin/sed
sed     14855 root  mem    REG  253,0 48508544 2559248 /usr/lib/locale/locale-archive
sed     14855 root  mem    REG  253,0    21546 2589098 /usr/lib64/gconv/gconv-modules.cache
sed     14855 root  mem    REG  253,0   182160 2589145 /usr/lib64/gconv/GB18030.so
sed     14855 root  mem    REG  253,0   105080 3997927 /lib64/ld-2.3.4.so
sed     14855 root  mem    REG  253,0  1489097 3997928 /lib64/tls/libc-2.3.4.so
sed     14855 root    0u   CHR  136,3                5 /dev/pts/3
sed     14855 root    1w  FIFO    0,7           130511 pipe
sed     14855 root    2u   CHR  136,3                5 /dev/pts/3
sed     14855 root    3r   REG  253,0    48894 5367617 /home/user1/file1
sed     14855 root    4u   REG  253,0    28263 5367609 /home/user1/sed0cb2We
先說(shuō)明一下,這里用lsof工具監視sed打開(kāi)的文件,你也許需要su成為root才行。另外sed處理的文件不能太短,讓lsof可以抓到。
請看最后兩行,倒數第二行是sed處理的目標文件,最后一行是...
哈哈,抓到了!sed偷偷地打開(kāi)了一個(gè)文件。
讓我們再看清楚一點(diǎn):

# seq 1000000 >file1
# sed -i ‘1,10d‘ file1|{ lsof -a +r 1 -c sed -d3,4;}
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
sed     16030 root    3r   REG  253,0 6888894 5367609 /home/user1/file1
sed     16030 root    4u   REG  253,0   31778 5367617 /home/user1/sedmXZuni
=======
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
sed     16030 root    3r   REG  253,0 6888894 5367609 /home/user1/file1
sed     16030 root    4u   REG  253,0 1613492 5367617 /home/user1/sedmXZuni
=======
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
sed     16030 root    3r   REG  253,0 6888894 5367609 /home/user1/file1
sed     16030 root    4u   REG  253,0 3285078 5367617 /home/user1/sedmXZuni
=======
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
sed     16030 root    3r   REG  253,0 6888894 5367609 /home/user1/file1
sed     16030 root    4u   REG  253,0 4959317 5367617 /home/user1/sedmXZuni
=======
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
sed     16030 root    3r   REG  253,0 6888894 5367609 /home/user1/file1
sed     16030 root    4u   REG  253,0 6631246 5367617 /home/user1/sedmXZuni
=======
這次處理的文件加大了,lsof每1秒鐘采樣一次??梢钥吹脚R時(shí)文件越來(lái)越大,最后接近原文件的大小。

如此我們可以推論:sed -i的處理過(guò)程是先將輸出寫(xiě)入一個(gè)臨時(shí)文件,然后自動(dòng)將臨時(shí)文件改名為原文件,--就像前面我們手工做的那樣。
這樣的話(huà),用sed -i只是方便了一點(diǎn),并沒(méi)有空間占用上的優(yōu)勢。

那么是不是就非用C不可呢?別急,flw在本版曾給出過(guò)一個(gè)perl腳本(請參看:如何不需要更多的空間,去掉文件的首位注釋行?),為了和上面的 例子對應,改寫(xiě)如下:

$ cat t.pl
#!/usr/bin/perl
$fn = shift;
open R, "<$fn";
open W, "+<$fn";
while(<R>){
print W if $. > 10
}
truncate( W, tell(W) );
這段代碼用兩個(gè)句柄打開(kāi)要處理的文件,處理的結果寫(xiě)回原文件,最后截斷文件的長(cháng)度以適應處理后的結果。很明顯這里沒(méi)有用到任何中間文件。
經(jīng)測試,腳本工作得很好,而且性能比sed要高出一個(gè)量級。

$ seq 100000 >file1
$ time ./t.pl file1

real    0m0.075s
user    0m0.073s
sys     0m0.002s

$ seq 100000 >file1
$ time sed -i ‘1, 10d‘ file1

real    0m0.417s
user    0m0.134s
sys     0m0.283s
可以相信,性能的差距主要是臨時(shí)文件的IO造成的,如果去掉-i選項,sed的性能會(huì )好很多,與perl在一個(gè)量級上:

$ time sed ‘1, 10d‘ file1 >/dev/null

real    0m0.072s
user    0m0.071s
sys     0m0.001s
相應的perl代碼的性能也相近:

$ time perl -ne ‘print if $. > 10‘ file1 >/dev/null

real    0m0.071s
user    0m0.070s
sys     0m0.001s
由此可見(jiàn)flw的代碼效率相當高,額外的磁盤(pán)IO很少。


至此我們終于有一種方法解決了大文件的空間占用問(wèn)題。似乎可以大功告成,收兵回營(yíng)了。但是再等一下,flw的代碼性能雖好,但還是稍微麻煩了一點(diǎn)。有沒(méi)有性能又好編寫(xiě)又簡(jiǎn)單的方法呢?
上面我們已經(jīng)討論過(guò)sed的-i選項,我們知道perl也有-i選項,實(shí)際上GNU sed的-i選項應該是從perl借鑒過(guò)去的。既然sed -i性能很差,perl -i性能究竟如何呢?關(guān)鍵在于,它是否會(huì )使用中間文件--因為那會(huì )引入很多磁盤(pán)IO。我們來(lái)測試看看:

$seq 100000 >file1
$ time perl -i -ne ‘print if $. > 10‘ file1

real    0m0.076s
user    0m0.070s
sys     0m0.006s
不錯!性能和flw的代碼相差不大。這似乎說(shuō)明沒(méi)有中間文件,我們來(lái)驗證一下:

# perl -i -ne ‘print if $. > 10‘ file1|lsof -a -c perl -d0-9
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
perl    16279 root    0u   CHR  136,3               5 /dev/pts/3
perl    16279 root    1w  FIFO    0,7          136352 pipe
perl    16279 root    2u   CHR  136,3               5 /dev/pts/3
perl    16279 root    3r   REG  253,0 6888602 5367617 /home/user1/file1 (deleted)
perl    16279 root    4w   REG  253,0  225280 5367609 /home/user1/file1
如我們所料:perl打開(kāi)了file1兩次,沒(méi)有中間文件。對比一下flw代碼的情況:

# ./t.pl file1|lsof -a -c t.pl -d0-9
COMMAND   PID USER   FD   TYPE DEVICE    SIZE    NODE NAME
t.pl    16294 root    0u   CHR  136,3               5 /dev/pts/3
t.pl    16294 root    1w  FIFO    0,7          136475 pipe
t.pl    16294 root    2u   CHR  136,3               5 /dev/pts/3
t.pl    16294 root    3r   REG  253,0 6888562 5367609 /home/user1/file1
t.pl    16294 root    4u   REG  253,0 6888562 5367609 /home/user1/file1
讓我們再加大文件試試:

$ seq 10000000 >file1
$ time ./t.pl file1

real    0m7.810s
user    0m7.524s
sys     0m0.284s

$ seq 10000000 >file1
$ time perl -i -ne ‘print if $. > 10‘ file1

real    0m7.825s
user    0m7.189s
sys     0m0.635s
如上,flw的代碼sys時(shí)間較少,反映其IO耗時(shí)較少,但user時(shí)間稍長(cháng)點(diǎn),可能是在顯式的while循環(huán)上吃虧的緣故??偟膩?lái)看兩者差距微小。

至此,我們已經(jīng)得到了perl處理大文件的兩種方法,兩者性能相差無(wú)幾,但perl -i更加簡(jiǎn)單,可以寫(xiě)出漂亮的單行腳本--one liner,推薦大家優(yōu)先使用。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
使用sed和awk命令刪除第一列
生成exl文件
五種方法實(shí)現Linux批量重命名文件
高級Unix命令 | 酷殼 - CoolShell.cn
sed?基礎,語(yǔ)句格式
25個(gè)好用的Shell腳本常用命令分享
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久