使用Awk / Sed - 需要在File中将值增加5(发生在XML但不能使用xml工具)

时间:2016-02-12 14:04:36

标签: xml bash awk sed

我今天早上一直在看一些帖子。有些人非常接近我需要的东西。

我有一个文件,其中包含多行正在使用的网络端口。我需要创建不同的文件,值需要以5的增量更改。

该文件包含100行(示例),但我只关注“ports”标记内的数据。

实施例

<parent>
<config>
<config1 label="Configuration1 Port">41502</config1>
<config2 label="Configuration2 Port">61160</pls_vimvom>
</config>
<ports>
<donttouch label="Base Port">1234</donttouch>
<op_var_tank label="Tank Port">41502</op_var_tank>
<pls_vimvom label="Local Port">61160</pls_vimvom>
<pls_xxx label="Local Port">11110-11120</pls_xxx>
</ports>
<extra>
More here
</extra>
</parent>

我需要保留带有“donttouch”标签的行,但要更改其他行。此行始终包含<donttouch></donttouch>

标记

我想用41507替换41502,用61165替换61160(依此类推......) 我能够设置如下的硬编码值:(我需要增量)

sed -i -e '/<ports>/,/<\/ports>/ s|Port">[0-9a-z.]\{1,\}</|Port">1234567</|g' text2.xml 

静态的分隔符来自

Port">

</

我需要确保只更改父标记“”和“”

之间的内容

所以我的预期输出来自上面(递增5)

<parent>
<config>
<config1 label="Configuration1 Port">41502</config1>
<config2 label="Configuration2 Port">61160</pls_vimvom>
</config>
<ports>
<donttouch label="Base Port">1234</donttouch>
<op_var_tank label="Tank Port">41507</op_var_tank>
<pls_vimvom label="Local Port">61165</pls_vimvom>
<pls_xxx label="Local Port">11115-11125</pls_xxx>
</ports>
<extra>
More here
</extra>
</parent>

谢谢!

**编辑以反映我的完整要求,感谢Ed *

1 个答案:

答案 0 :(得分:3)

如果您的数据始终是常规数据(例如,不在标签内的行之间拆分),那么您只需要:

$ cat tst.awk
BEGIN { FS="[<>]" }
/<\/?ports>/ { inPorts = !inPorts }
inPorts && !/<donttouch/ {
    new = ""
    split($3,range,/-/)
    for (i=1;i in range;i++) {
        new = (i>1 ? new "-" : "") range[i] + 5
    }
    sub(/>[^<]+</,">"new"<")
}
{ print }

$ awk -f tst.awk file
<parent>
<config>
<config1 label="Configuration1 Port">41502</config1>
<config2 label="Configuration2 Port">61160</pls_vimvom>
</config>
<ports>
<donttouch label="Base Port">1234</donttouch>
<op_var_tank label="Tank Port">41507</op_var_tank>
<pls_vimvom label="Local Port">61165</pls_vimvom>
<pls_xxx label="Local Port">11115-11125</pls_xxx>
</ports>
<extra>
More here
</extra>
</parent>

请注意,您可以在awk中使用范围表达式(/<ports>/,/<\/ports>/),就像您必须在sed中一样,因为不支持变量,但设置标志(inPorts)总是更好的选择因为当需求发生变化而不需要重复条件或完全重写时,它提供了更大的灵活性。