免费注册 查看新帖 |

Chinaunix

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

shell脚本--对原文件的每行记录操作,写入到新文件,速度运行慢,请大虾指点 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-14 19:49 |只看该作者 |倒序浏览
一个文本处理的脚本,数据量比较大,运行速度慢,希望大虾们指点
源文件大概如下:
01|02|03|04|05
01|02|03|04|05
01|02|03|04|05
01|02|03|04|05
01|02|03|04|05
01|02|03|04|05
……
原始文件大小不确定,以50万行为例

目标文件要求如下:
abc|20110514000000|01|03|05
abc|20110514000000|01|03|05
abc|20110514000000|01|03|05
abc|20110514000000|01|03|05
abc|20110514000000|01|03|05
abc|20110514000000|01|03|05    注:第二个字段20110214000000是取当前操作时间
……
50万行

源文件每一行的记录以'|'为字段分隔符,要求取出第1,3,5个字段,并在新的记录前插入abc和20110514000000(当前操作时间)两个字段。
还要求目标文件不能超出指定大小,如果超出则写入新文件。并且生成文件名从0000-9999序号来生成。例:abcdef_0000.dat 到 abcdef_9999.dat
我的思路是
nowtime=`date +%Y%m%d%H%M%S`
for record in $(cut -d '|' -f1,3,5 源文件名)
do
   echo "abc|$nowtime|取出字段“  >  目标文件
   if  超出指定大小
   then
         新建目标文件
   fi
done

现在的问题是
1.如果在插入一行后,怎样判断目标文件的大小是否超出。
2.如果源文件数据量比较大,一行一行的操作会比较慢,而且每插入一行,还要判断是否
超出指定大小,这样肯定比较费时,有没有批量执行的命令或则更快的命令?
3.可不可以在插入完后,判断文件的大小,用split命令来按照规定的文件大小来分割,
也就是  “if  超出指定大小”这个判断放在for循环的外面,但如果是这样的话,文件名
又比较难生成。因为split分割的文件是从1开始递增的,那如果我现在的文件流水号是5
那么操作起来就比较麻烦。

论坛徽章:
0
2 [报告]
发表于 2011-05-14 20:14 |只看该作者
自己来顶一个

论坛徽章:
0
3 [报告]
发表于 2011-05-14 20:21 |只看该作者
本帖最后由 南极雨 于 2011-05-14 20:26 编辑

回复 1# C307307


    这样肯定慢...用awk和sed吧
备份原文件!!!
  1. nowtime=`date +%Y%m%d%H%M%S`;sed "s/^/abc\|$nowtime/" file | awk '{print $1,$2,$4,$5,$6}'
复制代码
  1. nowtime=`date +%Y%m%d%H%M%S`;sed -e "s/\(.*\)|02\(.*\)/\1\2/;s/^/abc|$nowtime/" file
复制代码
-e可以删除,第二个应该比第一个快点儿

论坛徽章:
0
4 [报告]
发表于 2011-05-14 20:37 |只看该作者
谢谢楼上,我去试试。

论坛徽章:
0
5 [报告]
发表于 2011-05-14 20:54 |只看该作者
第一个代码我没看明白,前面的sed是在每行前面插入字段,那后面这个awk是做什么用的,而且这个管道命令貌似没用。

论坛徽章:
0
6 [报告]
发表于 2011-05-14 20:59 |只看该作者
麻烦南极雨说明下,第二个代码的这个  "s/\(.*\)|02\(.*\)/\1\2/ 是做什么用的?

论坛徽章:
0
7 [报告]
发表于 2011-05-14 21:24 |只看该作者
第二个段代码明白了,就是去掉了“|02”这个字段

论坛徽章:
0
8 [报告]
发表于 2011-05-14 21:56 |只看该作者
回复 5# C307307


也是去掉    “|02”这个字段

论坛徽章:
0
9 [报告]
发表于 2011-05-15 10:39 |只看该作者
本帖最后由 ywlscpl 于 2011-05-15 10:43 编辑

我想楼主说的源文件中内容可能并不是像举例的那样内容都是一样的,那么按文件大小来分割得话只能用split了
  1. awk -F '|' -v time=`date +%Y%m%d%H%M%S` '{print "abc|"time"|"$1"|"$3"|"$5}' file >file1
  2. split -b 5M -d file1
  3. ls x0* |awk -Fx '{d=sprintf("%04d",$2);system("mv "$0" abcdef_"d".dat")}'
  4. rm -f file1
复制代码
ywlscpl@ubuntu:~$ split --version
split (GNU coreutils) 6.10
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Torbjorn Granlund and Richard M. Stallman.

论坛徽章:
0
10 [报告]
发表于 2011-05-15 11:58 |只看该作者
谢谢ywlscpl:
楼上理解的正是,另外文件分割的流水号问题也帮我解决了。
另谢谢南极雨。

Ps:
1.nowtime=`date +%Y%m%d%H%M%S`;sed  "s/\(.*\)|\(.*\)|\(.*\)|\(.*\)|\(.*\)/\1|\3|\5/;s/^/abc|$nowtime|/" file > file1

2.awk -F '|' -v time=`date +%Y%m%d%H%M%S` '{print "abc|"time"|"$1"|"$3"|"$5}' file >file1

两段代码的运行速度都很快阿 ,31万条记录,第一端代码用了5秒左右,第二段代码稍快一点,2秒左右。
但是输出标准输出的话第一个稍快,20秒左右,第二个25秒左右。(自己统计的,文本内容不一样的话,时间可能会有所偏差。)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP