LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2443|回复: 21

如何用sed以最简单的方式实现这样的字符替换?

[复制链接]
发表于 2004-12-4 14:20:35 | 显示全部楼层 |阅读模式
有这样的一个文件
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DOPRW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DPRW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DNRW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DRW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DOPW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DPW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DNW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MOPRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MPRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MNRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MOPW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MPW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MNW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2YOPRW

现在要求把GM2_后面没有c字符的条目都该为GM2_c,同时再将改好后的GM2_c 和以有的GM2_c 都替换成/opt/at_sing/GM2_c
如果要写成一个脚本文件,以 command file参数 来执行又该怎么写呢?
发表于 2004-12-4 15:48:20 | 显示全部楼层

  1. perl -pi -e 's@GM2_c?@/opt/at_sing/GM2_c@' datafile
复制代码
发表于 2004-12-4 17:01:28 | 显示全部楼层
cat datafile | sed 's/GM2_SFC/GM2_cSFC/g' | sed 's/GM2_c/?opt?at_sing?GM2_c/g' | tr '?' '/'
 楼主| 发表于 2004-12-4 23:18:00 | 显示全部楼层
谢谢楼上的两位大哥阿
不过可惜peal我用不来阿
三楼的方法不错,不过请问一下, 最后的那个| tr '?' '/'
是表示什么意思阿
发表于 2004-12-5 20:45:55 | 显示全部楼层
tr --help
Usage: tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input,
writing to standard output.

tr '?' '/'
把所有的?字符替换成/

因为要求GM2_c 都替换成/opt/at_sing/GM2_c
如果执行sed 's/GM2_c//opt/at_sing/GM2_c/g'会error,又不知道在sed里替换字符串如何转义,所以用了点小trick,先换成?opt?at_sing?GM2_c,再把?换成/,就成了/opt/at_sing/GM2_c
发表于 2004-12-6 12:32:18 | 显示全部楼层
bb
 楼主| 发表于 2004-12-6 17:32:00 | 显示全部楼层
最初由 cisco 发表
tr --help
Usage: tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input,
writing to standard output.

tr '?' '/'
把所有的?字符替换成/

因为要求GM2_c 都替换成/opt/at_sing/GM2_c
如果执行sed 's/GM2_c//opt/at_sing/GM2_c/g'会error,又不知道在sed里替换字符串如何转义,所以用了点小trick,先换成?opt?at_sing?GM2_c,再把?换成/,就成了/opt/at_sing/GM2_c


我发现sed真得很灵活,可以用别的来替换/,所以可以写成
's:GM2_c:/opt/at_sing/GM2_c:g' 就可以了
 楼主| 发表于 2004-12-6 17:47:53 | 显示全部楼层
但是主要的问题是,类似的文件有很多,都要进行修改。比如还有
/opt/fg/bin/peercmd store 0.0 GM3_P2DOPV
/opt/fg/bin/peercmd store 0.0 GM3_P2DPV
/opt/fg/bin/peercmd store 0.0 GM3_P2DNV
/opt/fg/bin/peercmd store 0.0 GM3_P2DV
/opt/fg/bin/peercmd store 0.0 GM3_cP2MOPRV
/opt/fg/bin/peercmd store 0.0 GM3_cP2MPRV
/opt/fg/bin/peercmd store 0.0 GM3_cP2MNRV
/opt/fg/bin/peercmd store 0.0 GM3_cP2MRV
还有
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DRW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DOPW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DPW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DNW
/opt/fg/bin/peercmd store 0.0 GM2_SFC2DW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MOPRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MPRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MNRW
/opt/fg/bin/peercmd store 0.0 GM2_cSFC2MRW
等等这些文件都要修改
所以现在就有一个问题,应该如何替换。如果只将GM2_替换成GM2_c 然后再进行全局替换,后面几行会得到GM2_cc的结果。而cisco所写的又只能对特定的那个文件才能有效的替换。
所以我想问问sed能不能做到同时适配两个patten的替换,就是同时将GM1_ 和 GM1_c 替换成/opt/at_sing/GM1_c  。
发表于 2004-12-6 22:56:48 | 显示全部楼层
晕。兄弟你的算法思维很差。
正好比山顶有一根木头,山腰有一根木头,要把两根木头都搬到山下。你们怎么做呢?你们先把山腰的木头搬上山顶~~,再将山顶两根木头一起搬到山下。
看到问题了吗?——你和cisco兄都做了无用功!

我怎么做?把山顶的木头搬到山腰时顺带把山腰的木头一起搬下去。就这么简单!


你说perl你不会用。但起码知道perl其实在模拟sed的行为吧。我之所以用perl,就是为了省去临时文件!你可以用sed来做,其正则表达式是通用的。

这个任务的关键在于正则表达式的构建。

GM3_c?
里面的?就是将前面的c匹配0或1次,也就是说,匹配了两种情况,GM3_c或者GM3_。

希望兄弟们学习Shell之前先温习一下数据结构和算法思维。另外,我早已经在上面给出答案。希望以后进一步发问之前先尊重一下别人给出的回答。

ps:我比前任kornlee斑竹直率,得罪之处多包涵。
发表于 2004-12-6 23:08:31 | 显示全部楼层
最初由 cisco 发表
cat datafile | sed 's/GM2_SFC/GM2_cSFC/g' | sed 's/GM2_c/?opt?at_sing?GM2_c/g' | tr '?' '/'

在sed里,如果不想替换字符串中的字符和默认定界符'/'闹冲突,可以换另一个合法定界符。
如sed '@stringA@stringB@'。而无需很傻地加上?后再用tr来换?。这是基本的语法问题,希望兄弟以后注意改正。

另外,如果要并列多个sed操作句,用分号';'来分隔即可。
即sed 'process1;process2;...processN'
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表