天天看点

sed 实例备忘

需求:

修改所有automation script目录下的build config file。每个feature下面都会有至少一个个build config file,文件名为:build.cfg, build_6.9.cfg ...

需要在每个build config file搜索 关键字:INCLUDE_PING 或 INCLUDE_PING6.

如果找到了关键字,则需要插入:INCLUDE_IPPING_CMD 或 INCLUDE_IPPING6_CMD

而关键字出现的位置可能有四种:

1. 开头,但不是结尾:

vip_components_t1 = "INCLUDE_PING \

这种情况需要插入目标行到关键字行下面行即可;

目标效果:

vip_components_t1 = "INCLUDE_PING \

                           INCLUDE_IPPING_CMD \

2. 中间,非开头非结尾:

 vip_components_t2 = "INCLUDE_SHELL \

        INCLUDE_SHELL_INTERP_CMD \

        INCLUDE_PING \

        INCLUDE_PING6 \

        INCLUDE_IPPING6_CMD"

这种情况,需要添加目标行到关键字上方或者下方都可以。

目标效果:

 vip_components_t2 = "INCLUDE_SHELL \

        INCLUDE_SHELL_INTERP_CMD \

        INCLUDE_PING \

        INCLUDE_IPPING_CMD \

        INCLUDE_PING6 \

        INCLUDE_IPPING6_CMD \

        INCLUDE_IPPING6_CMD"

3. 结尾。

vip_components_t2 = "INCLUDE_SHELL \

        INCLUDE_SHELL_INTERP_CMD \

        INCLUDE_PING"

这种情况,需要添加目标行到关键字行的上一行。

目标效果:

vip_components_t2 = "INCLUDE_SHELL \

        INCLUDE_SHELL_INTERP_CMD \

         INCLUDE_IPPING_CMD \

        INCLUDE_PING"

4. 开头,同时也是结尾

vip_components_t2 = "INCLUDE_PING"

这种情况稍微复杂一些,需要插入目标行到关键字行下方,同时关键字之后的双引号也要替换成反斜线。

目标效果:

vip_components_t2 = "INCLUDE_PING \

                          INCLUDE_IPPING_CMD"

解决方案:

分析之后,其实情况1, 2都可以用一个sed表达式解决,情况3 需要另外写一个表达式。 由于情况4的case很少,而且稍微复杂一些,没有用sed解决(留着以后思考)

sed 表达式:

find . -name "build*.cfg" |xargs sed -e '/INCLUDE_PING\>\s*\\/a\    INCLUDE_IPPING_CMD\ \\' -e '/INCLUDE_PING6\>\s*\\/a\    INCLUDE_IPPING6_CMD\ \\' -e '/[^\"]\s*INCLUDE_PING\>\s*\"/i\    INCLUDE_IPPING_CMD\ \\' -e '/[^\"]\s*INCLUDE_PING6\>\s*\"/i\    INCLUDE_IPPING6_CMD\ \\' -i

该表达式解决了情况1,2,3, 为了解决情况4:

 find . -name "build*.cfg" |xargs grep -niHr \"INCLUDE_PING\"

然后根据搜索出来的文件名,分别手动修改(笨方法)。

需求二:

需要把所有的build cfg文件中的字符 .* 或  .*? 替换成为 [0-9_]+

这个需求的有意义的地方:

1. 找到所有的 build cfg文件,这些文件的名字有build_7.cfg, build_7_MSP.cfg

find . -name build_7*.cfg

2. 字符 .* [ ] 等都是特殊含义字符,需要转意

 sed -e 's/\.\*?/\[0-9_\]+/g' -e 's/\.\*/\[0-9_\]+/g' -i

所以一个命令:

 find . -name build_7*.cfg | xargs sed -e 's/\.\*?/\[0-9_\]+/g' -e 's/\.\*/\[0-9_\]+/g' -i

需求三:

*这是sed和find的一次结合使用

在build config file中,过去使用了类似: IPNET_[0-9_]+_IPSECIKE_[0-9_]+_IPSEC_[0-9_]+ 正则表达式结构,但后续的软件版本没有了这样的结构,修改为类似:IPNET_IPSEC 的结构。并且赋值也从原来的1,改变为y。

这样的修改需要更改很多的文件,不可能手动一个一个的修改,于是使用sed 命令:

sed -i -e 's/IPNET_\[0-9_\]+_IPSECIKE_\[0-9_\]+_IPSEC_\[0-9_\]+ *1/IPNET_IPSEC y/g' build_7.cfg

这样的修改能满足需求,但是由于修改量比较大,而且有许多类似结构的内容需要修改,手动一个一个命令执行压力太大。

于是需要创建一个sed脚本,把要修改的所有命令都放在文件中,然后一次执行全部解决。

于是逐条写好修改的命令,然后执行:

find . -name build_7*.cfg -exec sed -f workspace/sed_script.txt '{}' \;

问题解决。

中间出现了小插曲,记录如下:

当在生成sed 脚本文件的时候,由于第一次使用,直接把命令行执行的命令写入sed 脚本文件,例如:

's/IPNET_\[0-9_\]+_DHCPC_\[0-9_\]+ *1/IPNET_DHCPC y/g'

's/IPNET_\[0-9_\]+_DHCPC6_\[0-9_\]+ *1/IPNET_DHCPC6 y/g'

但sed脚本文件中不能再有单引号,不然就会报错,于是需要删除所有的单引号。使用了vim中的命令:

:%s/'//g

这样文件中所有的单引号被删除。

如果用::s/'//g

则只能删除一行中的单引号,而不是文件中的全部单引号。