Chinaunix

标题: sed读取配置批量替换 [打印本页]

作者: 代号:军刀    时间: 2013-11-21 16:32
标题: sed读取配置批量替换
本帖最后由 代号:军刀 于 2013-11-21 17:42 编辑

现在有一个配置文件config,里面的内容为:
<SERVERID> 1
<SERVER_NAME> aaaaa
... ...
还有很多类似于上面的这种定义
.
.

我需要把dir目录下所有的文件,比如a.txt内容为
1
2
3
SERVERID=<SERVERID>
4
给替换成
1
2
3
SERVERID=1
4

b.txt的内容为
5555
<SERVERID>
<SERVER_NAME> fdsaf

给替换成
5555
1
aaaaa fdsaf

就是有关dir目录下的所有文件都按config文件定义的做替换,我之前使用的是傻瓜式的写法,变量定义所有config的内容,然后find查找,接着sed和-e连成一串替换,这样不好的地方在于每次我config增加一条内容,那我就得改脚本增加一个变量和一条sed,shell的数组又不支持像awk那样使用下标进行存储。不知大家有没有更好的方案,不要一个个定义config文件的变量,但替换效率也要高一点的
作者: yestreenstars    时间: 2013-11-21 17:07
find命令你根据实际情况改改:
  1. [root@localhost ~]# head test/*
  2. ==> test/a <==
  3. <a>

  4. ==> test/b <==
  5. <b>

  6. ==> test/c <==
  7. <c>
  8. [root@localhost ~]# cat t
  9. <a> 1
  10. <b> 2
  11. <c> 3
  12. [root@localhost ~]# find /root/test -type f | xargs awk 'NR==FNR{a[$1]=$2;next}$0 in a{$0=a[$0]}{print > FILENAME}' t
  13. [root@localhost ~]# head test/*
  14. ==> test/a <==
  15. 1

  16. ==> test/b <==
  17. 2

  18. ==> test/c <==
  19. 3
  20. [root@localhost ~]#
复制代码

作者: 代号:军刀    时间: 2013-11-21 17:22
回复 2# yestreenstars


    你这种不行呀,你使用的是$0 in a,我都不知道替换的字符在行的哪个位置,你这个是要替换的字符都是把它当成是一行,比如替换字符在 a <a> b,那你使用$0 in a就不生效了
作者: yestreenstars    时间: 2013-11-21 17:27
回复 3# 代号:军刀
还有什么状况?
  1. [root@localhost ~]# head test/*
  2. ==> test/a <==
  3. 1
  4. 2
  5. 3
  6. <SERVERID>
  7. 4

  8. ==> test/b <==
  9. 5555
  10. <SERVERID>
  11. <SERVER_NAME> fdsaf
  12. [root@localhost ~]# cat t
  13. <SERVERID> 1
  14. <SERVER_NAME> aaaaa
  15. [root@localhost ~]# find /root/test -type f | xargs awk 'NR==FNR{a[$1]=$2;next}{for(i=1;i<=NF;i++)if($i in a)$i=a[$i]}{print > FILENAME}' t
  16. [root@localhost ~]# head test/*
  17. ==> test/a <==
  18. 1
  19. 2
  20. 3
  21. 1
  22. 4

  23. ==> test/b <==
  24. 5555
  25. 1
  26. aaaaa fdsaf
  27. [root@localhost ~]#
复制代码

作者: 代号:军刀    时间: 2013-11-21 17:32
回复 4# yestreenstars


    还真有状况,你使用的是for(i=1;i<=NF;i++)   $i in a
    我要替换的文件里面存着类似server_name=<server_name>这个时候你的$1 in a又匹配不到,还是sed稳妥点,awk漏洞百出
作者: 关阴月飞    时间: 2013-11-21 17:34
回复 5# 代号:军刀


    事实上你原来的方法不就挺好的么
作者: yestreenstars    时间: 2013-11-21 17:36
回复 5# 代号:军刀
没办法,我是根据你给的数据写的~

   
作者: 代号:军刀    时间: 2013-11-21 17:38
回复 6# 关阴月飞


    原来的方法每次更改config文件,我都要改脚本,congfig增加的多,脚本我也要改得多,config的内容增多,我每次都要定义变量,造成了脚本也看起来臃肿
作者: 代号:军刀    时间: 2013-11-21 17:41
回复 7# yestreenstars


    好吧,我的错
作者: 关阴月飞    时间: 2013-11-21 17:42
回复 8# 代号:军刀


    但是这个config文件是替换的依据,维护这个文件也是不可避免的,如果不通过这种方式,能有别的方法自动生成这个文件不?

作者: reyleon    时间: 2013-11-21 17:45
回复 4# yestreenstars


    为什么文件内容没有被重写?好神奇
作者: yestreenstars    时间: 2013-11-21 17:46
  1. [root@localhost ~]# head test/*
  2. ==> test/a <==
  3. 1
  4. 2
  5. 3
  6. <SERVERID>
  7. 4

  8. ==> test/b <==
  9. 5555
  10. <SERVERID>
  11. <SERVER_NAME> fdsaf

  12. ==> test/c <==
  13. server_name=<server_name>
  14. [root@localhost ~]# cat t
  15. <SERVERID> 1
  16. <SERVER_NAME> aaaaa
  17. [root@localhost ~]# find /root/test -type f | xargs awk -vIGNORECASE=1 'NR==FNR{a[$1]=$2;next}{for(i in a)gsub(i,a[i])}{print > FILENAME}' t
  18. [root@localhost ~]# head test/*
  19. ==> test/a <==
  20. 1
  21. 2
  22. 3
  23. 1
  24. 4

  25. ==> test/b <==
  26. 5555
  27. 1
  28. aaaaa fdsaf

  29. ==> test/c <==
  30. server_name=aaaaa
  31. [root@localhost ~]#
复制代码
效率嘛,我没大量数据可测~
作者: 代号:军刀    时间: 2013-11-21 17:46
回复 10# 关阴月飞


    这个配置文件要手动维护的,没办法自动生成,老是改脚本不是好方法呀,这样容易把脚本改出问题
作者: reyleon    时间: 2013-11-21 17:46
难不成 awk 是 根据行号对应重写行的?
作者: yestreenstars    时间: 2013-11-21 17:49
回复 14# reyleon
你之前不是也接触过吗?
print expr-list >file Prints  expressions  on file.  Each expression is separated by the value of the OFS variable.  The output record
                             is terminated with the value of the ORS variable.


   
作者: 代号:军刀    时间: 2013-11-21 17:55
回复 12# yestreenstars


    不知怎么了,用awk来匹配替换写文件不太自信,等会我试试看
作者: reyleon    时间: 2013-11-21 18:06
回复 15# yestreenstars


    但这个读也是这个文件,写也是这个文件,是同一个文件呐
作者: 关阴月飞    时间: 2013-11-21 18:09
本帖最后由 关阴月飞 于 2013-11-21 18:09 编辑

回复 12# yestreenstars


    这对同时对同一文件又读又写的,感觉不太稳当,容易随机地出现各种神秘现象, 感觉还是整个大循环,先写临时文件,再mv来的放心。
作者: reyleon    时间: 2013-11-21 18:14
关阴月飞 发表于 2013-11-21 18:09
回复 12# yestreenstars


不是,按理不能又读又写,比如:
  1. [root@centos6-1 testf]# seq 10 > file
  2. [root@centos6-1 testf]# sort -r file > file
复制代码
这样是先清空了file文件,因为标准输出和标准错误的管道的优先级要高,然后再对file文件排序,但是这个时候已经没内容了还怎么读啊?

--------------

引用网中人的话:

  1. $ cat < file > file
  2. $ cat < file
  3. 复制代码


  4. 嗯?﹗注意到沒有?﹗﹗
  5. ---- 怎麼最後那個 cat 命令看到的 file 竟是空的?﹗
  6. why? why? why?

  7. 同學們:下節課不要遲到囉~~~!


  8. --------------
  9. 11.5
  10. 噹噹噹~~~ 上課囉~~~ ^_^

  11. 前面提到:$ cat < file > file 之後原本有內容的檔案結果卻被洗掉了﹗
  12. 要理解這一現像其實不難,這只是 priority 的問題而已:
  13. * 在 IO Redirection 中,stdout 與 stderr 的管道會先準備好,才會從 stdin 讀進資料。
  14. 也就是說,在上例中,> file 會先將 file 清空,然後才讀進 < file ,
  15. 但這時候檔案已經被清空了,因此就變成讀不進任何資料了...
复制代码

作者: yestreenstars    时间: 2013-11-21 18:41
回复 18# 关阴月飞
其实我也不太清楚具体的流程,但感觉是借助临时文件处理的~

   
作者: 代号:军刀    时间: 2013-11-21 20:35
本帖最后由 代号:军刀 于 2013-11-21 20:39 编辑

@reyleon@yestreenstars@关阴月飞我知道为什么又写又读没事,因为print的时候文件已经读完了
作者: reyleon    时间: 2013-11-22 11:24
回复 21# 代号:军刀


    哪里读完了,木有吧
作者: 代号:军刀    时间: 2013-11-22 11:43
回复 22# reyleon


    我也是猜的,但是如果没读完的话,替换的文件应该只会剩下一行才对,因为使用的>而不是>>




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