中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > 综合其它
一个Shell程序的性能优化(1)
作者:佚名 时间:2007-09-24 16:32 出处:中国IT实验室 责编:月夜寒箫
              摘要:一个Shell程序的性能优化(1)

本文Shell程序运行环境:

◆程序运行环境Redhat Linux As3

◆GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu)

◆代码清单:shellcode.txt



问题描述:有一个普通的通话话单文件(包括“计费号码”,“主叫号码”,“被叫号码”,“开始时间”,“结束时间”,“时长”,“费用”等其它字段),要求根据另外一个号段配置文件(由“号段下限”和“号段上限”两个字段组成)将此话单文件进行分拣过虑。

分拣规则:如果通话话单文件中的“计费号码”位于号段文件的某个号段内,则将此条记录计入结果文件1,否则计入结果文件2。

通话话单文件样例:

9013320003|9013320003|9918128025|20060814163420|20060814163450|30|20|00|01|005

9926645208|9926645208|9918188065|20060814163415|20060814163545|90|30|00|01|005

9934877207|9934877207|9936972003|20060814163620|20060814163930|190|50|00|01|005

......

......

号段配置文件样例:

9013305000,9013327999

9013767000,9013768999

9923670000,9923679999

9928998000,9928999999

9932310000,9932319999

9932333400,9932333599

9936034000,9936036999

9936084000,9936084999

9998537000,9998537999

9998620000,9998629999

9998690000,9998699999

例如:

对于通话话单文件的第一条记录中的“计费号码”为9013320000,此号码正好属于号段配置文件的第一个号段9013305000,9013327999中,即:条件9013305000<= 9013320000 <=9013327999成立,所以应该将通话话单文件的第一条记录计入结果文件1中;对于通话话单文件中的第二条记录的“计费号码”为9926645208它不属于号段文件中的任何一个段,所以应该将通话话单的第二条记录计入结果文件2中。

对于这样一个简单的问题首先想到的解决方法为:

解决方法1:

写一个双重循环,外层循环为逐条读取“通话话单文件”并获取每条记录的第一个字段的值“计费号码”,内层循环:根据外层循环获得的“计费号码”在“号段文件”中循环比较,判断此号码是否属于相应号段。

程序代码如下(省略了文件存在性判断等语句):

            

while read f

do

org="$(expr substr ${f} 1 10)"   #取得"计费号码"存入变量org中

while read numseg

do

nglow="$(expr substr ${numseg} 1 10 )"   #将号段下限存入变量nglow

ngtop="$(expr substr ${numseg} 12 10 )"  #将号段上限存入变量ngtop

if [ "$org" \> "$nglow"  -a "$org" \< $ngtop ]

#判断"计费号码"是否在此号段内

then

echo "${f}" >> ./resultfile1.cdr #如果在此号段内,将此记录计入结果文件1中

else

echo "${f}" >> ./resultfile2.cdr #如果不在此号段内,将此记录计入结果文件2中

fi

done < ./numseg.txt

done < ./rttest.txt

解决方法1对于号段文件和通话话单的记录数都比较少的情况下基本可以完成工作,但是当两个文件的记录数较多(例如号段文件>50条,话单文件>10000条)的时候,这种方法就会花费几个小时甚至几天的时间才能得出处理结果。此脚本程序执行慢的原因是对第二个循环内的比较运算只用了最简单的顺序比较方法,所以当号段文件的记录增多的时候,脚本的执行速度会急剧下降。

解决方法2:

将内层循环的逐个比较的方法改为二分查找法进行判断,程序代码如下:

            

#!/bin/bash

#Author Xsh  date:08-15-2006

#程序中使用了二分查找法进行号码的范围判断

#为突出重点,省略了文件存在性判断和异常捕获以及帮助提示等程序语句

#程序的工作目录为当前目录

echo "Time:$(date)==>Strat to processing........." #显示程序开始运行时间

while read numseg

do

tmplow="${tmplow} $(expr substr ${numseg} 1 10 & >/dev/null ) "

tmptop="${tmptop} $(expr substr ${numseg} 12 10 & >/dev/null ) "

done < ./numseg.txt

#读取号段文件,下限号段存入变量tmplow,上限号段存入变量tmptop

arr_lownug=(${tmplow}) #将下限号段存入数组arr_lownug

arr_topnug=(${tmptop}) #将上限号段存入数组arr_topnug

#定义函数checknum(),输入参数为需要检查的"计费号码",输出参数为0或者1

#若checknum()输出为0 表示"计费号码" 不在号段文件的所有号段范围内

#若checknum()输出为1 表示"计费号码" 在号段文件的所有号段范围内

# checknum()函数中用二分搜索法进行号码的判断

checknum(){

thisnum=$1

ckresult=0

lowflag=0

topflag=$(expr ${#arr_lownug[*]} - 1 )  #标注1

MaxIndex=$(expr ${#arr_topnug[*]} - 1 ) #标注2

midflag=0

midflag=$(expr ${topflag} / 2 )  #标注3

if [ "${thisnum}" \< "${arr_lownug[0]}" -o "${thisnum}" \>

"${arr_topnug[${MaxIndex}]}"  ]

then

return 0

else

while [ "$lowflag" != "$midflag" ]

do

if[ "$thisnum" \> "${arr_lownug[${midflag}]}" -o "$thisnum" == \

"${arr_lownug[${midflag}]}" ]

then

lowflag=${midflag}

midflag=$(expr `expr ${topflag} + ${lowflag}` / 2 ) #标注4

elif["$thisnum"\<"${arr_lownug[${midflag}]}" -o "$thisnum" == \

"${arr_lownug[${midflag}]}" ]

then

topflag=${midflag}

midflag=$(expr `expr ${topflag} + ${lowflag}` / 2 ) #标注5

else

echo "Error!"  

fi

done

if [ "$thisnum" \< "${arr_topnug[${lowflag}]}" -o "$thisnum" == \

"${arr_topnug[${lowflag}]}" ]

then

return 1

else

return 0

fi

fi

}#函数定义完毕

while read f

do

org="$(expr substr ${f} 1 10)" #标注6

checknum ${org}

returnval=$?

if [ "$returnval" == "1"  ]

then

echo "${f}" >> ./Match_result.cdr  #将匹配的记录存入结果文件1

else

echo "${f}" >> ./NoMatch_result.cdr #将不匹配的记录存入结果文件2

fi

done < ./rttest.txt

echo "Time:$(date) ==> Proccess is end! "

exit 0;

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有