Chinaunix

标题: 能否使用sed+正则表达式替换指定行的指定内容 [打印本页]

作者: lnzfm    时间: 2014-12-04 02:25
标题: 能否使用sed+正则表达式替换指定行的指定内容
某文件夹下有三个文件,内容如下
1.txt
$host   = "1.1.1.1";
$host   = "1.1.1.1";
$host   = "1.1.1.1";
$host   = "1.1.1.1";


2.txt
$host   = '11.11.11.11';
$host   = '11.11.11.11';
$host   = '11.11.11.11';
$host   = '11.11.11.11';

3.txt
$host   = <111.111.111.111>;
$host   = <111.111.111.111>;
$host   = <111.111.111.111>;
$host   = <111.111.111.111>;


整理出需要替换内容的列表保存在replace.me的文件里,格式为
文件名:需替换的行号        该行的内容

1.txt:1                $host   = "1.1.1.1";
2.txt:2                $host   = '11.11.11.11';
3.txt:3                $host   = <111.111.111.111>;

能否使用sed+正则表达式将replace.me的文件里每个文件名里出现的ip地址用正则表达式进行匹配,并将匹配到的地址替换为2.2.2.2,替换后的结果为
1.txt
$host   = "2.2.2.2";
$host   = "1.1.1.1";
$host   = "1.1.1.1";
$host   = "1.1.1.1";


2.txt
$host   = '11.11.11.11';
$host   = '2.2.2.2';
$host   = '11.11.11.11';
$host   = '11.11.11.11';

3.txt
$host   = <111.111.111.111>;
$host   = <111.111.111.111>;
$host   = <2.2.2.2>;
$host   = <111.111.111.111>;
作者: zooyo    时间: 2014-12-04 08:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: klainogn    时间: 2014-12-04 09:02
本帖最后由 klainogn 于 2014-12-04 09:12 编辑
  1. $ sed -r 's/^(.*):([0-9]+).*=[^0-9]*([0-9\.]+)[^0-9]+$/sed "1F;\2 s#\3#2.2.2.2#" \1/e;' re.me
  2. 1.txt
  3. $host   = "2.2.2.2";
  4. $host   = "1.1.1.1";
  5. $host   = "1.1.1.1";
  6. $host   = "1.1.1.1";
  7. 2.txt
  8. $host   = '11.11.11.11';
  9. $host   = '2.2.2.2';
  10. $host   = '11.11.11.11';
  11. $host   = '11.11.11.11';
  12. 3.txt
  13. $host   = <111.111.111.111>;
  14. $host   = <111.111.111.111>;
  15. $host   = <2.2.2.2>;
  16. $host   = <111.111.111.111>;
复制代码
如果直接修改原文件,修改为以下内容:
  1. sed -r 's/^(.*):([0-9]+).*=[^0-9]*([0-9\.]+)[^0-9]+$/sed -i "\2 s#\3#2.2.2.2#" \1/e;' re.me
复制代码

作者: zerostudy    时间: 2014-12-04 09:10
回复 3# klainogn


     厉害!
作者: Looiml    时间: 2014-12-04 10:11
3楼对sed中s/e命令的运用确实是妙到豪颠啊,相对而言awk看起来就太臃肿了:

  1. awk 'BEGIN{FS="[: <>;\"'"'"'=]+";while(getline <"replace.me"){a[$1]=$2;b[$1]=$4}} a[FILENAME]==FNR{gsub(b[FILENAME],"2.2.2.2")}{print >FILENAME"new"}' files
复制代码

作者: ly5066113    时间: 2014-12-04 10:24
回复 5# Looiml
  1. awk -F '[: ]+' '{n=0;while(getline v<$1){if(++n==$2)sub(/\<[0-9.]+\>/,"2.2.2.2",v);print v>$1".new"}}' replace.me
复制代码

作者: Looiml    时间: 2014-12-04 10:49
回复 6# ly5066113
类似的方式,不过有误,把\< \>拿掉应该就好了,如果人家要匹配到replace.me里的最后一列才做替换的话可能还得改改,不过跟sed比起来,要做原文件替换的话,又得多加些字符。
作者: Looiml    时间: 2014-12-04 10:52
回复 6# ly5066113
不过客观地讲,兄弟的方法可以准确地找文本文件,不必另外花功夫,值得借鉴。
   
作者: lnzfm    时间: 2014-12-04 11:03
[ 本帖最后由 lnzfm 于 2014-12-04 11:53 编辑 ]

谢谢各位,我有个地方没看懂,麻烦帮我解释一下。
我感觉替换都是在后面的sed "1F;\2 s#\3#2.2.2.2#" \1/e;这部分完成的,可是为什么
s/^(.*):([0-9]+).*=[^0-9]*([0-9\.]+)[^0-9]+$前面这里使用s/替换模式呢?
我们的口号是更短,更快,更简洁
作者: blackold    时间: 2014-12-04 12:25
回复 9# lnzfm


    谍中谍,sed中sed。

   这相当于两个sed命令。
作者: klainogn    时间: 2014-12-04 13:09
本帖最后由 klainogn 于 2014-12-04 13:10 编辑

e是把pattern空间里的内容做为shell命令来执行的,所以需要依据当前pattern空间的内容来生成一个合理可执行的shell命令并替换原pattern空间的全部内容
作者: ckf513728912    时间: 2014-12-04 14:06
写得很妙啊  
作者: zjj2006forever    时间: 2014-12-05 11:49
初学,请教下这个是什么意思啊,尤其是括号里面那段sed -i "\2 s#\3#2.2.2.2#" \1/e;请大牛帮忙解释下




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