Tuesday, August 12, 2014


Shell Script - Update Fields in plist/xml (data serialization) file - after specific field match - using awk


We face the need to update the XML, where tag value or key-value pairs needs to be modified, using shell script. Tried the below way:

Say XML file appears like:


<?xml version="1.0" encoding="UTF-8"?>
<key>Server</key>
<lex>
<key>Location</key>
<string>Homestead</string>
<key>days</key>
<integer>60</integer>
</lex>

<key>server</key>
<lex>
<key>host</key>
<string>ab.host.com</string>
<key>days</key>
<integer>30</integer>
</lex>

Now we want to update the field host value. The below script call can do it:
./updatexml.sh bcd.host.com

where updatexml.sh looks like:

#! /bin/bash

var=$1

awk -F'[<>]' '
        /<key>Client<\/key>/ {
                f = 1
        }
        /<key>host<\/key>/ {
                s = 1
        }

        {
if (f && s && /<value>/) {
sub($3,"'$var'",$0); 
f = 0
s = 0
        }
print 
}
' 1.xml > temp.xml
mv temp.xml 1.xml 

Explanation:
set a flag 'f', after the occurrence of the tag "<key>Client</key>" and on finding occurrence of "<key>host</key>" set another flag. Then it is self explicable, on match of both flags true and tag <value> we replace the third column of line with variable.

Sort list of IP Addresses using LINUX/UNIX sort utility:


sort -t'.' -k 1,1 -k 2,2 -n -k 3,3 -k 4,4 1.txt

where
-t specifies field separator
-k specifies the field, on which sorting is happening

       -t, --field-separator=SEP
              use SEP instead of non-blank to blank transition

       -k, --key=POS1[,POS2]
              start a key at POS1, end it at POS2 (origin 1)


cat 1.txt
243.242.6.254
192.21.64.1
156.20.4.92
30.160.5.20
30.20.12.1
30.20.5.1



O/P;
30.20.5.1
30.20.12.1
30.160.5.20
156.20.4.92
192.21.64.1
243.242.6.254