简体   繁体   English

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

[英]Using Awk/Sed - Need to increment value by 5 in File ( Happens to be XML but cant use xml tools)

Ive been looking at a number of posts this morning. 我今天早上一直在看一些帖子。 Some get very close to what I need. 有些人非常接近我需要的东西。

I have a file that contains multiple lines of Network ports in use. 我有一个文件,其中包含多行正在使用的网络端口。 I need to create different files and the values need to change by an increment of 5. 我需要创建不同的文件,值需要以5的增量更改。

The file contains 100 lines ( example ) but Im only concerned with data within the "ports" tag. 该文件包含100行(示例)但我只关注“ports”标记内的数据。

Example

<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>

I need to retain the line with tag "donttouch" but change others. 我需要保留带有“donttouch”标签的行,但要更改其他行。 This line will always have the tags <donttouch> to </donttouch> 此行将始终具有<donttouch></donttouch>标记

I want to replace 41502 with 41507 , and 61160 with 61165 ( and so on.. ) I was able to set a hardcoded value as follows: ( I need an increment ) 我想用41507替换41502,用61165替换61160(依此类推..)我能够设置如下硬编码值:(我需要增量)

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

The Delimiter that's static is from 静态的分隔符来自

Port">

to

</

I need to make sure I only change the content between parent tags "" and "" 我需要确保我只更改父标签“”和“”之间的内容

So my expected output from the above ( incrementing by 5 ) 所以我的预期输出来自上面(递增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>

Thanks! 谢谢!

**Edited to reflect my complete requirement , thanks Ed* **编辑以反映我的完整要求,感谢Ed *

If your data is always that regular (eg not split across lines within tags) then all you need is: 如果您的数据始终是常规的(例如,不在标签内的行之间拆分),那么您只需要:

$ 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>

Note that you CAN use a range expression ( /<ports>/,/<\\/ports>/ ) in awk just like you MUST do in sed due to no support for variables, but setting a flag ( inPorts ) is always a better alternative as it provides much more flexibility if/when requirements change without needing duplicate conditions or a complete rewrite. 请注意,您可以在awk中使用范围表达式( /<ports>/,/<\\/ports>/ ),就像您必须在sed中一样,因为不支持变量,但设置标志( inPorts )总是更好如果/当需求发生变化而不需要重复条件或完全重写时,它提供了更大的灵活性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM