免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3419 | 回复: 14
打印 上一主题 下一主题

[文本处理] 如何用awk或sed优化单据编号统计的脚本 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-08-03 03:02 |只看该作者 |倒序浏览
请教各位高手:
环境: RedHat6,用了4分30秒.
单据编号从00001到99999。经过多年,多科室的使用,出现了碎片化。脚本就是对此的统计。
输入文件是已经使用的单据编号:UsedFormNo.txt
00001
00002
00005
00010
00011
00013
....

输出文件:
nouse.txt:未使用的编号,
00003
00004
00006
00007
00008
00009
00012
....
nousedrange.csv:未使用编号的起止编号和张数,如果未使用单据编号连续
00003-00004,2
00006-00009,4
....
usedrange.csv:已使用编号的起止编号和张数,如果编号连续
00001-00002,2
00005-00005,1
00010-00011,2
....
脚本:
date
rm -f nouse.txt usedrange.csv nousedrange.csv
touch nouse.txt usedrange.csv nousedrange.csv
prevused="0"
count=0
counter=0
i=1
while read UsedNo
do
   usedno=`expr $UsedNo`
   currused=$usedno
   j=`expr $prevused + 1`
   if [ $usedno -eq $j ]; then
      count=`expr $count + 1`
   elif [ $usedno -gt $j ]; then
      beginused=`expr $j - $count`
      beginused=`expr $beginused - 1`
      prevused=`expr $j - 1`
      count=`expr $count + 1`
      echo $(printf "%05d" $beginused)"-"$(printf "%05d" $prevused)","$count>>usedrange.csv
      count=0
   fi
   while [ $i -lt $usedno ]
   do
      counter=`expr $counter + 1`
      echo $(printf "%05d" $i) >> nouse.txt
      i=`expr $i + 1`
      if [ $i -eq $usedno ]; then
         endnoused=`expr $usedno - 1`
         begnoused=`expr $usedno - $counter`
         echo $(printf "%05d" $begnoused)"-"$(printf "%05d" $endnoused)","$counter>>nousedrange.csv
         counter=0
      fi
   done
   while [ $i -eq $usedno ]
   do
      i=`expr $i + 1`
   done
   prevused=$usedno
done < UsedFormNo.txt
date

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
2 [报告]
发表于 2014-08-03 12:19 |只看该作者
本帖最后由 欧阳西风 于 2014-08-03 12:42 编辑

回复 1# schrosourcexuey

现在正好在做awk的练习,就用awk来写一个吧(awk属于菜鸟级水平,请大家指正)
  1. $ awk -f danju.awk danju.txt
  2. $ cat danju.awk
  3. {
  4. ncount=$0-prev-1
  5. if(ncount!=0){
  6.   printf("%05d-%05d,%d\n",prev-ucount+1,prev,ucount) >>"use.csv"
  7.   ucount=0
  8.   for(i=ncount;i>=1;i--){
  9.     printf("%05d\n",$0-i) >>"nouse.txt"
  10.   }
  11.   printf("%05d-%05d,%d\n",prev+1,$0-1,ncount) >>"nouse.csv"
  12. }
  13. prev=$0
  14. ucount=ucount+1
  15. }
复制代码
另外 我没有那么多的数据,所以执行效率不清楚如何,lz可以那你的数据测试一下,或者提供一段测试数据我们来测试一下效率。

论坛徽章:
5
白羊座
日期:2014-10-28 11:23:27水瓶座
日期:2015-01-20 10:19:022015亚冠之柏斯波利斯
日期:2015-07-11 18:17:2015-16赛季CBA联赛之同曦
日期:2015-12-23 12:38:582016猴年福章徽章
日期:2016-02-18 15:30:34
3 [报告]
发表于 2014-08-03 13:04 |只看该作者
本帖最后由 klainogn 于 2014-08-03 13:46 编辑

更大的菜鸟来了,代码肯定是不够简练,但应该比纯shell处理来的快点吧
  1. BEGIN{
  2.     total=20000
  3. }
  4. {
  5.     for(;i++<total;){
  6.         sept=","
  7.         if(+$1==i){
  8.             if(last_use+1==+$1) {u_cnt++;sept="-"}
  9.             use=use?use sept $1"-"$1:$1"-"$1
  10.             use=gensub(/([0-9]+-)[^,]*-([0-9]+)/,"\\1\\2", "g",use)
  11.             if(use~/,/){
  12.                 print substr(use,0,11)","u_cnt >"use.txt"
  13.                 use=substr(use,13)
  14.                 u_cnt=1
  15.             }
  16.             last_use=$1
  17.             next
  18.         }else{
  19.             if(last_nouse+1==i) {n_cnt++;sept="-"}
  20.             sn=sprintf("%05d",i)
  21.             nouse=nouse?nouse sept sn"-"sn:sn"-"sn
  22.             nouse=gensub(/([0-9]+-)[^,]*-([0-9]+)/,"\\1\\2", "g",nouse)
  23.             if(nouse~","){
  24.                 print substr(nouse,0,11),n_cnt >"nouse.txt"
  25.                 nouse=substr(nouse,13)
  26.                 n_cnt=1
  27.             }
  28.             last_nouse=sn
  29.             continue
  30.         }
  31.     }

  32. }
  33. END{
  34.     print use","u_cnt >"use.txt"
  35.     print nouse","n_cnt >"nouse.txt"
  36.                            
  37.     if(++i<total){
  38.         print sprintf("%05d",i)"-"total","total-i >"nouse.txt"
  39.     }
  40. }
复制代码

论坛徽章:
5
白羊座
日期:2014-10-28 11:23:27水瓶座
日期:2015-01-20 10:19:022015亚冠之柏斯波利斯
日期:2015-07-11 18:17:2015-16赛季CBA联赛之同曦
日期:2015-12-23 12:38:582016猴年福章徽章
日期:2016-02-18 15:30:34
4 [报告]
发表于 2014-08-03 13:42 |只看该作者
本帖最后由 klainogn 于 2014-08-03 13:53 编辑

屌爆了,可以直接升级成为大神, 这个ncount用的神了回复 2# 欧阳西风


   

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
5 [报告]
发表于 2014-08-03 13:44 |只看该作者
回复 4# klainogn


    过奖了 现在还是有待提高啊 awk平时用的不多 现在正在有意练习中...

另外 问一下不知道刚刚的脚本的运行效率如何?因为我没有进行效率测试

论坛徽章:
5
白羊座
日期:2014-10-28 11:23:27水瓶座
日期:2015-01-20 10:19:022015亚冠之柏斯波利斯
日期:2015-07-11 18:17:2015-16赛季CBA联赛之同曦
日期:2015-12-23 12:38:582016猴年福章徽章
日期:2016-02-18 15:30:34
6 [报告]
发表于 2014-08-03 13:51 |只看该作者
效率我也没有测试过,不过肯定会比shell快吧, 你的代码计算一下最后使用的编号到最大编号的部分,那就完美了回复 5# 欧阳西风


   

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
7 [报告]
发表于 2014-08-03 14:19 |只看该作者
回复 6# klainogn


    恩 这个问题倒是好办。不过呢 你这一说 我又发现了我之前脚本的一点儿小问题,就是use.csv当中并没有打印最后的use数据,所以脚本还是需要改进的,一会儿我再看一下。

    不过呢,你可以通过临时的解决方法来解决我提到的问题和你的需求,那就是在源数据的末尾手动添加最大编号+1的值,即:
  1. echo 100000 >> danju.txt
复制代码

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
8 [报告]
发表于 2014-08-03 14:36 |只看该作者
回复 6# klainogn


    刚刚又修改了一下,不过看起来代码就有点儿多了,我再去看看awk的自定义函数,学会了以后看看能不能搞个函数,里面有几个都是重复的东西
  1. $cat danju.awk
  2. BEGIN{
  3. MAXNUMBER=99999
  4. }
  5. {
  6. ncount=$0-prev-1
  7. if(ncount!=0){
  8.   printf("%05d-%05d,%d\n",prev-ucount+1,prev,ucount) >>"use.csv"
  9.   ucount=0
  10.   for(i=ncount;i>=1;i--){
  11.     printf("%05d\n",$0-i) >>"nouse.txt"
  12.   }
  13.   printf("%05d-%05d,%d\n",prev+1,$0-1,ncount) >>"nouse.csv"
  14. }
  15. prev=$0
  16. ucount=ucount+1
  17. }
  18. END{
  19. if(ucount!=0){
  20.   printf("%05d-%05d,%d\n",prev-ucount+1,prev,ucount) >>"use.csv"
  21. }
  22. if(prev<MAXNUMBER){
  23.   ncount=MAXNUMBER-prev
  24.   for(i=ncount;i>=1;i--){
  25.     printf("%05d\n",MAXNUMBER+1-i) >>"nouse.txt"
  26.   }
  27.   printf("%05d-%05d,%d\n",prev+1,MAXNUMBER,ncount) >>"nouse.csv"
  28. }
  29. }
复制代码

论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-08-24 06:20:00综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00IT运维版块每日发帖之星
日期:2015-10-25 06:20:00IT运维版块每日发帖之星
日期:2015-11-06 06:20:00IT运维版块每日发帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT运维版块每日发帖之星
日期:2016-04-15 06:20:00IT运维版块每日发帖之星
日期:2016-05-21 06:20:00综合交流区版块每日发帖之星
日期:2016-08-16 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-14 06:20:00
9 [报告]
发表于 2014-08-03 15:51 |只看该作者
哥最爱此类问题,awk解决的标配啊。可惜心情不好,不想写。

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
10 [报告]
发表于 2014-08-03 15:54 |只看该作者
回复 9# expert1


    心情不好才更应该写啊 写一写代码心情就好起来啦哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP