user9843902
user9843902

Reputation: 1

Increase version number by one in next line using awk

I need to use awk to increase the version number by one in the line after a unique string.

Original:

<key>UniqueKey</key>
<string>100</string>

Desired output

<key>UniqueKey</key>
<string>101</string>

Unfortunately "string" is not unique in the file, so I have to modify the line after the unique "key" string. I need to take the number, whatever it may be, and increase it by one. The command will be running in a virtual workspace that gets deleted each time, so a simple awk command would be preferred.

Upvotes: 0

Views: 104

Answers (3)

karakfa
karakfa

Reputation: 67467

$ awk -F'[<>]' '$3=="UniqueKey"{n=NR} 
   n && NR==n+1 && $2=="string"{sub($3,$3+1)}1' file

<key>UniqueKey</key>
<string>101</string>

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203334

$ awk -F'[<>]' '$2=="string" && p3=="UniqueKey" { sub(/>[^<]+/,">"$3+1) } {p3=$3} 1' file
<key>UniqueKey</key>
<string>101</string>

Upvotes: 0

kvantour
kvantour

Reputation: 26471

This looks remarkably like an XML file. It is strongly recommended to use XML-related tools for this job such as xmlstarlet.

Assuming a given input file of the form :

<header>
  <node>
    <key>UniqueKey</key>
    <foo />
    <string>100</string>
  </node>
  <node>
    <key>UniqueKey</key>
    <string>101</string>
    <string>200</string>
  </node>
</header>

Then the following command will update as requested :

$ xmlstarlet ed -u '//key[text()="UniqueKey"]/following-sibling::string[1]' \
                -x '(text()+1)' file.xml

This does the following :

  • ed: enter editing mode
  • -u <xpath>: update the nodes matched by xpath

    • //key: select any node with name key
    • //key[text()="UniqueKey"]: select any node with the name key and value "UniqueKey"
    • //key[text()="UniqueKey"]/following-sibling::string: pick the first 'string' siblings of key that follows key
  • -x '(text()+1)' : update the selected nodes value by the expression text()+1

The output is then given by :

<?xml version="1.0"?>
<header>
  <node>
    <key>UniqueKey</key>
    <foo/>
    <string>101</string>   # change
  </node>
  <node>
    <key>UniqueKey</key>
    <string>102</string>   # change
    <string>200</string>   # no change
  </node>
</header>

Or if it realy has to be the next node, then you need to play a trick with concat and substring as xpath-1.0 does not have if conditions. More details here

$ xmlstarlet ed -u '//key[text()="UniqueKey"]/following-sibling::*[1]' \
                -x 'substring(text()+1,1,number(name()="string")*string-length(text()+1))' file.xml

<?xml version="1.0"?>
<header>
  <node>
    <key>UniqueKey</key>
    <foo/>
    <string>100</string>   # no change
  </node>
  <node>
    <key>UniqueKey</key>
    <string>102</string>   # change
    <string>200</string>   # no change
  </node>
</header>

Upvotes: 0

Related Questions