0

i have this given xml which i need to change only 1 element in it which will be always under the title string the (THIS_IS_NEED_TO_CHANGE) , currently i change it using sed

sudo sed -i -E 's/_THIS_IS_NEED_TO_CHANGE_/_NEW_STR_/g' the_file.xml"

but this is wrong as the "THIS_IS_NEED_TO_CHANGE" can be changed to another string

<plist version="1.0">
        <dict>
                <key>items</key>
                <array>
                        <dict>
                                <key>metadata</key>
                                <dict>
                                        <key>bundle-identifier</key>
                                        <string>xxxx</string>
                                        <key>bundle-version</key>
                                        <string>xxxx</string>
                                        <key>kind</key>
                                        <string>software</string>
                                        <key>platform-identifier</key>
                                        <string>xxxxx</string>
                                        <key>title</key>
                                        <string>_THIS_IS_NEED_TO_CHANGE_</string>
                                </dict>
                        </dict>
                </array>
        </dict>
        </plist>

** UPDATE **
I can't install any other Linux apps
I need to do it with the default installed Linux tools

user63898
  • 29,839
  • 85
  • 272
  • 514

1 Answers1

0

Without any additional tools, you can use awk redirecting the output to a tmp file and then move that tmp file back to the original. So using the file plist with the source data in the example:

awk -v yourtext="_NEW_STR3_" -F [\<\>] '/<key>/ { field=$3;print $0 } /<string>/ { if (field=="title") { match($0,$3);printf "%s%s%s\n",substr($0,1,RSTART-1),yourtext,substr($0,RSTART+RLENGTH,length($0)) } } !/<string>/&&!/key>/ {print $0}' plist > plist.tmp && mv -f plist.tmp plist

This sets the field delimiters to < or > and passes the new contents to be printed as the variable yourtext. It then checks for lines with <key> and gets the contents, placing them in the variable field. With lines containing <string>, if the field variable has previously been set to title then print the line up to the string contents, print the new contents (contained in the variable "yourtext") and then print the remaining portion of the line. In all other instances, just print the line as is.

Alternatively you can use sed:

sed -Ei '/<key>title<\/key>/ {n;s/(^.*<string>)(.*)(<\/string>$)/\1_NEW_STR_4\3/g}' plist

Search for the line <key>title<\key> and then move to the next line and split the line into three sections specified in brackets. Print the first section then the amended text and then the final third section

Raman Sailopal
  • 12,320
  • 2
  • 11
  • 18