首页 > 代码库 > 优化shell的文件读取操作

优化shell的文件读取操作

 前段时间经常在linux下对文件进行一些读取操作,可在操作得过程中发觉一些脚本的执行效率并不是很理想,下来认真的翻了一下《Mastering UNIX shell Scripting》,学习了一下其中对文件读取和写入得一些方法,在此进行总结记录。

       我们对文件得处理往往是通过循环得方式进行的,在循环中解析文件时,需要一种方法把整行得数据读入到一个变量中。最常见的命令是read。该命令很灵活,可用它读取单个字符串也可以读取整行。谈到读取整行,line是另一个可以读一行得命令。但一些操作系统并不支持line命令。除了read和line命令外,也需要查看一下while和for循环得不同方法,这是决定执行速度快慢得主要原因。在预定义得配置中可以把循环作为一个独立得循环来使用,可以用在命令管道中,也可以用文件描述符。每种方法有其自身得一套法则。如何利用循环得到最快得执行速度非常关键,也是决定一个处理文件脚本得关键因素。

       文件描述符:0 -stdin,1-stdout,2-stderr,在大多数操作系统中,有效得描述符的值为0到19,使用上述某些值时,必须做很多测试以便确认它们未被系统某种原因而保留。

        接下来我们通过一个shell中得time命令来测试不同方法处理文件的时间差,其中time会返回三个值分别为real user sys,代表得意思分别是: 总执行时间;用户/应用系统进程级花费得处理时间;系统在系统/内核级花费得处理时间,所有得计时数据都是输出到stderr或者标准错误,即文件描述符2,所以需要正确重定向标准错误输出进行查看。

        方法一:采用重定向标准输入,标准输出的方式。在处理中将标准输入重定向到文件描述附3,标准输出重定向到文件描述附4,并通过read逐行读取数据存入变量LINE中

[python] view plaincopy
  1. function while_read_LINE_FD_IN_AND_OUT  
  2. {  
  3.     >$OUTFILE  
  4.   
  5.     exec 3<&0  
  6.     exec 0< $INFILE  
  7.   
  8.     exec 4<&1  
  9.     exec 1> $OUTFILE  
  10.   
  11.     while read LINE  
  12.     do  
  13.         echo "$LINE"  
  14.         :  
  15.     done  
  16.   
  17.     exec 1<&4  
  18.     exec 4>&-  
  19.   
  20.     exec 0<&3  
  21.     exec 3>&-  
  22. }  

       方法二,仍旧采用文件描述符,但是采用line命令,执行方法如下:

[python] view plaincopy
  1. function while_LINE_line_FD_IN_AND_OUT  
  2. {  
  3.     >$OUTFILE  
  4.   
  5.     exec 3<&0  
  6.     exec 0< $INFILE  
  7.   
  8.     exec 4<&1  
  9.     exec 1> $OUTFILE  
  10.   
  11.     while LINE=`line`  
  12.     do  
  13.         echo "$LINE"  
  14.         :  
  15.     done  
  16.   
  17.     exec 1<&4  
  18.     exec 4>&-  
  19.   
  20.     exec 0<&3  
  21.     exec 3>&-  
  22. }  

     方法三,只重定向标准输出描述符,使用done<$INFILE输入重定向

[python] view plaincopy
  1. function while_read_LINE_bottom_FD_OUT  
  2. {  
  3.     >$OUTFILE  
  4.   
  5.     exec 4<&1  
  6.     exec 1>$OUTFILE  
  7.     while read LINE  
  8.     do  
  9.         echo "$LINE"  
  10.         :  
  11.     done < $INFILE  
  12.   
  13.     exec 1<&4  
  14.     exec 4>&-  
  15. }  

      方法四,不是用文件描述附:

[python] view plaincopy
  1. function while_read_LINE_bottom  
  2. {  
  3.     >$OUTFILE  
  4.   
  5.     while read LINE  
  6.     do  
  7.         echo "$LINE" >> $OUTFILE  
  8.         :  
  9.     done < $INFILE  
  10.   
  11. }  

     方法五,采用for循环的方式

[python] view plaincopy
  1. function for_LINE_cat_FILE_cmdsub2_FD_OUT  
  2. {  
  3.     >$OUTFILE  
  4.   
  5.     exec 4<&1  
  6.     exec 1> $OUTFILE  
  7.   
  8.     for LINE in $(cat $INFILE)  
  9.     do  
  10.         echo "$LINE"  
  11.         :  
  12.     done  
  13.   
  14.     exec 1<&4  
  15.     exec 4>&-  
  16. }  

    以上五种方法测试mysql.txt的一个描述文件得时间对比如下:

[plain] view plaincopy
  1. Method: function while_read_LINE_FD_IN_AND_OUT  
  2. real    0m0.312s  
  3. user    0m0.260s  
  4. sys 0m0.036s  
  5.   
  6. Method: function while_LINE_line_FD_IN_AND_OUT  
  7. real    0m6.347s  
  8. user    0m0.000s  
  9. sys 0m1.668s  
  10.   
  11. Method: function while_read_LINE_bottom_FD_OUT  
  12. real    0m0.261s  
  13. user    0m0.004s  
  14. sys 0m0.256s  
  15.   
  16. Method: function while_read_LINE_bottom  
  17. real    0m0.452s  
  18. user    0m0.244s  
  19. sys 0m0.204s  
  20.   
  21. Method: function for_LINE_cat_FILE_cmdsub2_FD_OUT  
  22. real    0m0.623s  
  23. user    0m0.388s  
  24. sys 0m0.232s  

       在对文件进行读取操作时,采用文件符明显快于不采用文件符的,采用read的快于采用line命令的,采用while循环读取文件的快于for循环的。

       在*nix平台上处理任何任务都有多种方法;一些文件处理技术浪费了大量得CPU时间,大多数浪费得时间花费在不必要得变量赋值以及连续地打开和关闭不同得文件上。在使用管道对循环计时也有负面影响,管道使用的文件大小最大不能超过2048个字符。

优化shell的文件读取操作