Y2theZ
Y2theZ

Reputation: 10402

using sed command to replace xml tags

in a project I have an info.plist (xcode project) file, which is an xml file. I would like to add more properties to it using a shell script on the terminal.

What I need to add to it is the following:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.myapp.test</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>test-scheme</string>
        </array>
    </dict>
</array>

After doing some research I found that the way to do it is to use the sed.

I will use the sed command to replace the first occurrence of the < dict > tag, which is always in the info.plist file, with the above code (and re-add < dict > at the start of it so I don't break the structure.

With the help of This Stackoverflow answer, I put together the following command:

sed ‘0,/<dict>/{s/<dict>/<dict><key>CFBundleURLTypes<\/key><array><dict><key>CFBundleTypeRole<\/key><string>Viewer<\/string><key>CFBundleURLName<\/key><string>com.myapp.test<\/string><key>CFBundleURLSchemes<\/key><array><string>test-scheme<\/string><\/array><\/dict><\/array>/}’ info.plist

Theoretically, that command should replace the first occurrence of `< dict >' tag with itself + the text I want to add, without line breaks. I also skipped the /

However when I run it I get the following error:

-bash: syntax error near unexpected token `<' 

What am I doing wrong? is there something I should do to make this work? I tried skipping all the < and > without success.

Any help is greatly appreciated.

EDIT

As suggested in the comments by JJoao I tried replacing sed ‘... ‘ with sed '...', now I get the following error:

sed: 1: "0,/<dict>/{s/<dict><key ...": unterminated substitute in regular expression

EDIT2

For more clarification, This is my desired output:

I have an xml file, that has the following:

<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
    <dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        .........
    </dic>
</plist>

I would like to insert the xml section I specified at the start. So the output would be:

<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
    <dict><key>CFBundleURLTypes</key><array><dict><key>CFBundleTypeRole</key><string>Viewer</string><key>CFBundleURLName</key><string>com.myapp.test</string><key>CFBundleURLSchemes</key><array><string>test-scheme</string></array></dict></array>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        .........
    </dic>
</plist>

Or to write it in a cleaner way:

<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
    <dict>
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLName</key>
                <string>com.myapp.test</string>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>test-scheme</string>
                </array>
            </dict>
        </array>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        .........
    </dic>
</plist>

Upvotes: 1

Views: 1561

Answers (1)

JJoao
JJoao

Reputation: 5347

perl -p behaves like sed; perl -p0 reads all lines of info.plist file

usage: perl changedict info.plist

#!/usr/bin/perl -p0

my $new='
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLName</key>
                <string>com.myapp.test</string>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>test-scheme</string>
                </array>
            </dict>
        </array>';

s!<dict>!<dict>$new!;

Update: The previous version is writing to standard output; You can redirect it to a newfile perl changedict info.plist > newinfo.plist.

If you need infile substitution, change the first line to

#!/usr/bin/perl -pi0

Upvotes: 1

Related Questions