编写高效的bash脚本

来源:互联网 发布:软件测试培训中心 编辑:程序博客网 时间:2024/05/19 22:03

1.      尽量将awk脚本写在bash脚本中,而不是放在单独的文件中。

 

在使用awk时,如果要有对较复杂的对文本的处理,我们习惯将其写在一个单独的文件中,使用时,如

echo "${params}"|awk -f conf/generate_sum.awk

但是这样会带来一定的性能的损耗。

推荐将awk脚本写在bash中,如,上面的例子可以写为:

 

 

 

echo "${params}"|awk '  BEGIN{

         FS项目="&"

         i=0 

 }   

 {   

         for(i=1;i<=NF;i++){

                 l=index($i,"=");

                 str=str substr($i,0,l);

         }   

 }   

 END{

         print str

 }'

 

试验:

采用上面的awk来分析一个75k的网页文件,循环100次。

采用第一种写法平均用时:43s

采用第二种写法平均用时:40s

在本次试验中,采用第二种写法能提高效率6.9%

 

对于sed脚本,同样有以上的建议。

 

2.      能用管道连接起来的一系列操作不要分开写。

 

管道帮助我们将一个程序的输出导入到另一个程序的输入。在处理数据时,很多时候需要一系列的处理。如果可以使用一系列的管道将处理连接起来,就尽量不要将每个处理分开来做。

例如:

我们用下列操作来得到数据link

link=$(echo "${params}"|awk -f conf/generate_sum.awk)

link=$(echo "$link"|sum -s)

link=$(echo "$link"|awk -F" " '{print $1}')

也可以采用如下的方法:

link=$(echo "${params}"|awk -f conf/generate_sum.awk|sum -s|awk -F" " '{print $1}')

实践表明采用方式二的效率会好些。

 

试验:

采用上面的脚本来处理一个75k的网页,循环100次。

采用第一种写法平均用时:73s

采用第二种写法平均用时:45s

在本次试验中,采用第二种写法能提高效率38.4%

 

3.      可以不使用管道时,减少管道的使用。

 

一个简单的例子是在文件的字符匹配时,我们可以使用

cat someweb|grep “href”

也可以使用

grep “href” someweb

推荐使用第二种方式。

 

试验:

采用上面的脚本循环10000次,得到的数据是:

采用第一种写法平均用时:13s

采用第二种写法平均用时:7s

第二种写法能提高效率46%

 

4.      尽可能的减少IO操作。

 

这点毋庸置疑。但是还是有些其他要说的。

在脚本运行中,许多中间变量的保存可以使用文件,尤其是父shell进程和子shell进程交互时,使用文件是比较方便的。其实,也有许多其他的方法。

这里要说一下父shell进程和子shell进程数据的共享。

一个问题是,子shell进程的环境变量,父shell进程是取不到的。如:

cat file|while read x

do

       ((line++))

done

printf “there are %d lines” $line

这时就打印不到行数。

解决的方法有:

使用文件保存line值,这里不推荐。

使用全局变量。

使用重定向。

这里推荐使用重定向。原因见下一条。

 

5.      尽量使用重定向,不用cat

 

如果对所有的脚本进行一下统计,那么使用的最多的几个命令当中,肯定有cat

如果你关心脚本的效率,那就尽早放弃cat。(下面的数据可能会更有说服力)

而实际上,cat能完成的功能,基本都可以用重定向来完成。

对于条目4的例子:

cat file|while read x

do

       ((line++))

done

推荐采用重定向完成:

(这同时也解决了父shell进程和子shell进程数据共享的问题)

while read x

do

       ((line++))

done < file

 

试验:

采用上面的脚本循环100次,文件为75k网页文件,得到的数据是:

采用第一种写法平均用时:11s

采用第二种写法平均用时:1s

第二种写法能提高效率91%

 

6.      不要使用递归

 

确实,bash也可以使用递归。

如果你才知道,那就当不知道吧。因此bash递归的效率非常的低。

 

7.      尽量使用内置命令,而不用同样功能的系统命令

 

对于内置命令,(可以通过man builtin查看),在执行的时候是不会产生子shell进程的。因此其执行速度会远远的高于系统命令。

例如:echo是一个bash内置的命令。当然,也存在和其功能相同的一个系统命令,名字也叫echo,在/bin/echo。这两个的性能差距是很大的。

我们可以比较下面两个简单的脚本:

/bin/echo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" >/dev/null

echo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" >/dev/null

 

试验:

采用上面的脚本循环20000次,得到的数据是:

采用第一种写法平均用时:13s

采用第二种写法平均用时:<1s

第二种写法能提高效率92%以上。

 

因此,在遇到一个功能的需求时,优先使用内置命令或其组合来完成,而不用系统或自己提供的命令和程序。

 

8.      其他

 

在你优化你的C代码的时候,很多程序设计的思想也是可以用到bash脚本设计中的。比如循环的优化,代码的模块化,结构化等。

实际上,对于一个脚本的优化,我们总是先找到其瓶颈在什么地方,然后考虑采用什么方法来进行。如果用尽所有方法也无法提高这块脚本的效率时,可以考虑将这块功能用C来实现。如果同时还考虑开发效率,那么可以考虑使用其他的脚本语言:perlpython等。