Chinaunix

标题: 文本内容替换的脚本,帮看是否能够优化一下 [打印本页]

作者: bugouhen    时间: 2009-12-28 10:48
标题: 文本内容替换的脚本,帮看是否能够优化一下
大家好
现手头有一批要替换的文本文件,写了个脚本请大家帮忙看一下是否能够再优化一下。这个循环太多了 速度实在是太慢

如下
a.txt
前后是新旧两组号码,要把指定文本的包含的旧号码,换成后面对应的新号码,大概300数据
140200003700.140200042852
142600009182.142600069906
142300003784.142300033332
142600009618.142600084180
142600038153.142600066756
142600002050.142600066015
142300003729.142300033319
142600014686.142600072919


tail 14_10002_2009348_VIP.DAT   这些DAT文件即为要替换的文本,每个DAT文件平均大概3w行数据左右
14,10002,2009348     ,14030065    ,100037,2009-12-21 19:59:37,2.00         ,140300020299,
14,10002,2009348     ,14270093    ,100247,2009-12-21 19:59:37,2.00         ,142700107999,
14,10002,2009348     ,14010023    ,100290,2009-12-21 19:59:37,2.00         ,140100141364
把后面的卡号 用a.txt中的对应内容替换

脚本:
for i in `cat name.txt `
do
cd DIR/$i
for a in `cat DIR/a.txt`
do
old=`echo $a |awk -F . {'print $1'}`
new=`echo $a |awk -F . {'print $2'}`
sed -i  s/"${old}"/"${new}"/g  DIR/$i/*.DAT
done
done

其中name.txt是一个 目录的列表 ,每个列表下有多个 DAT文件。大概200个目录,500个文件左右。

大家看一下我这个循环是否还能在优化一下  ,我测试了一下 跑起来实在是太慢了 全跑一次 大概要 一整天。。
或者能提供一个能提高一下速度的思路  

谢谢

[ 本帖最后由 bugouhen 于 2009-12-28 11:39 编辑 ]
作者: 莫良23    时间: 2009-12-28 11:15
sed和shell不要混用
作者: bugouhen    时间: 2009-12-28 11:19
麻烦 请楼上的 多解释一下好么
谢谢
作者: 莫良23    时间: 2009-12-28 11:24
把那个sed用shell来代替
作者: bugouhen    时间: 2009-12-28 11:26
原帖由 莫良23 于 2009-12-28 11:24 发表
把那个sed用shell来代替


把sed那句写成 sh
sh   sed.sh   ?


是这个意思吧 ??
这样会提升速度么 ??

xiexie

[ 本帖最后由 bugouhen 于 2009-12-28 12:27 编辑 ]
作者: nhw_cs    时间: 2009-12-28 11:49
原帖由 莫良23 于 2009-12-28 11:24 发表
把那个sed用shell来代替



淡有时候也可以扯, 但不能胡扯. 愿闻其详: shell与sed区别到底是啥啊
作者: ywlscpl    时间: 2009-12-28 12:17
不知道这样会不会快点?还是会更慢
  1. DIR="xxxx"
  2. for i in `cat name.txt `
  3. do
  4.   cd $DIR/$i
  5.   for file in *.DAT
  6.   do
  7.     awk -F, -v OFS=, 'NR==FNR{split($0,m,".");a[m[1]]=m[2];delete m}NR>FNR{if ($6 in a) $6=a[$6];$1=$1;print}' $DIR/a.txt $file >$file.new
  8.     \mv -f $file.new $file
  9.   done
  10. done
复制代码

作者: bugouhen    时间: 2009-12-28 12:26
原帖由 nhw_cs 于 2009-12-28 11:49 发表



淡有时候也可以扯, 但不能胡扯. 愿闻其详: shell与sed区别到底是啥啊




恩  请23 帮忙解释一下。。
谢谢

我现在是找了个性能好点的机器跑 感觉快了点哈
作者: bluewaterray    时间: 2009-12-28 12:42
用Hash做,原始值作为key,替换值作为value
作者: 莫良23    时间: 2009-12-28 13:04
每次用sed来处理100个文件肯定比100次调用sed每次处理一个文件要快
作者: bugouhen    时间: 2009-12-28 13:30
原帖由 莫良23 于 2009-12-28 13:04 发表
每次用sed来处理100个文件肯定比100次调用sed每次处理一个文件要快



您的意思是
先读取 新旧卡号变量
然后循环 sed 所有的文件


作者: merlin852    时间: 2009-12-28 13:36
大概200个目录,500个文件左右?
总共200*500=10w个文件,每个文件3w行?
作者: bugouhen    时间: 2009-12-28 13:41
原帖由 merlin852 于 2009-12-28 13:36 发表
大概200个目录,500个文件左右?
总共200*500=10w个文件,每个文件3w行?



sorry  总共 500个文件
作者: merlin852    时间: 2009-12-28 13:51
原帖由 bugouhen 于 2009-12-28 13:41 发表



sorry  总共 500个文件



sed -i  s/"${old}"/"${new}"/g  DIR/$i/*.DAT  -->

sed -i  s/"${old}"/"${new}"/g  DIR/$i/*.DAT  &
sleep 1
作者: 莫良23    时间: 2009-12-28 13:57
我只是提供个建议,我也是菜鸟,呵呵
作者: ly5066113    时间: 2009-12-28 14:34
标题: 回复 #7 ywlscpl 的帖子
肯定会比楼主的快。
不过 delete m 和 $1=$1 多余啊。

不过有更好的方案:
可以先把所有要处理的文件生成一个列表
然后用awk读a.txt一次,处理文件列表中的文件
这样a.txt和所有的DAT文件都只读一次就可以了
作者: bugouhen    时间: 2009-12-28 14:45
原帖由 ly5066113 于 2009-12-28 14:34 发表
肯定会比楼主的快。
不过 delete m 和 $1=$1 多余啊。

不过有更好的方案:
可以先把所有要处理的文件生成一个列表
然后用awk读a.txt一次,处理文件列表中的文件
这样a.txt和所有的DAT文件都只读一次就可以了



我把两个循环换一下先后顺序

[ 本帖最后由 bugouhen 于 2009-12-28 14:50 编辑 ]
作者: ywlscpl    时间: 2009-12-28 15:38
标题: 回复 #16 ly5066113 的帖子
delete m确实可有可无,但$1=$1是为了让OFS生效的
作者: ly5066113    时间: 2009-12-28 15:44
标题: 回复 #18 ywlscpl 的帖子
不需要啊,$6=a[$6] 就可以了
作者: beginner-bj    时间: 2009-12-28 15:53
我也觉得针对这个问题delete m没用,但不知道何时需要delete m?楼上两位大侠能否举个例子?
作者: ly5066113    时间: 2009-12-28 16:05
标题: 回复 #20 beginner-bj 的帖子
前些天好象有个列去重的问题,就是每行相同的列只输出一次。

awk '{for(i=1;i<=NF;i++) if(! a[$i]++) printf $i;print "";delete a}'
作者: curclew    时间: 2009-12-28 16:14
  1. DIR="$PWD"
  2. for i in $(<name.txt); do
  3.   cd $DIR/$i
  4.   awk -F, -v OFS=, 'NR==FNR{split($0,b,".");a[b[1]]=b[2];} NR>FNR{if ($8 in a) $8=a[$8];print $0 > FILENAME ".new"}' $DIR/a.txt *.dat
  5.   for j in *.dat;do
  6.   [ -f "$j.new" ] && mv -f "$j.new" "$j"
  7.   done
  8. done
复制代码

[ 本帖最后由 curclew 于 2009-12-28 16:16 编辑 ]
作者: ywlscpl    时间: 2009-12-28 16:49
原帖由 ly5066113 于 2009-12-28 15:44 发表
不需要啊,$6=a[$6] 就可以了


!($6 in a)的就不执行这句 $6=a[$6] 了
作者: ly5066113    时间: 2009-12-28 16:51
标题: 回复 #23 ywlscpl 的帖子
$0没变化,就原样输出啊,FS本就是 ,   为什么一定要 OFS 生效呢?
作者: ywlscpl    时间: 2009-12-28 16:54
标题: 回复 #24 ly5066113 的帖子
我错了。有时候脑袋一根筋,都没去想原来数据是怎样的
作者: korpus    时间: 2009-12-28 23:08
写程序会比SHELL更快么?
作者: deargodzw    时间: 2009-12-30 10:18
用C吧
作者: kilior    时间: 2009-12-30 11:47
for i in `cat xxxxx`
效率之低,浪费多少内才能,知道吗?
全给我改成:

  1. while read i ;do
  2. echo $i
  3. done << xxxxx
复制代码

作者: ywlscpl    时间: 2009-12-30 12:05
标题: 回复 #28 kilior 的帖子
你确定楼主的xxxx文件里是一行一个的?楼主可没说
作者: beginner-bj    时间: 2009-12-30 13:25
标题: 回复 #21 ly5066113 的帖子
好的,明白了。
作者: lbaby    时间: 2009-12-30 15:36
并行跑吧,这些数据没有关连的




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2