0

I have an XML file with content inside like following

<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
        <itemInstances>
            <componentInstance>
                <componentInstanceProperties>
                    <name>collapsed</name>
                    <value>false</value>
                </componentInstanceProperties>
    ...
    </itemInstances>
    <itemInstances>
        <componentInstance>
            <componentName>NameSpace:customList</componentName>
        </componentInstance>
    </itemInstances>
    <mode>Replace</mode>
    ...

I am trying to use awk to cut these lines out of the file.

I tried to run the following script

namespace="NameSpace"
component="customList"
awk "NR==FNR{if (/<componentName>$namespace:$component<\/componentName>/) for (i=-2;i<=2;i++) del[NR+i]; next} !(FNR in del)" file file 

but instead of cutting the desired lines, it chops off lines in the beginning of xml file and produces the following output

<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
            </componentInstanceProperties>
    ...
    </itemInstances>
    <itemInstances>
        <componentInstance>
            <componentName>NameSpace:customList</componentName>
        </componentInstance>
    </itemInstances>
    <mode>Replace</mode>
    ...

I tried to use variable substitution in different forms, like this

awk -v x="<componentName>$namespace:$component<\/componentName>" "NR==FNR{if ($0 ~ x) for (i=-2;i<=2;i++) del[NR+i]; next} !(FNR in del)" file source.xml

and this

awk -v x="<componentName>$namespace:$component</componentName>" "NR==FNR{if ($0 ~ x) for (i=-2;i<=2;i++) del[NR+i]; next} !(FNR in del)" file source.xml

but neither works. Is there any way to get this working?

Update: desired outcome to remove lines

    <itemInstances>
        <componentInstance>
            <componentName>NameSpace:customList</componentName>
        </componentInstance>
    </itemInstances>

so that result file looks like following

<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
        <itemInstances>
            <componentInstance>
                <componentInstanceProperties>
                    <name>collapsed</name>
                    <value>false</value>
                </componentInstanceProperties>
    ...
    </itemInstances>
    <mode>Replace</mode>
    ...
Patlatus
  • 1,217
  • 2
  • 16
  • 28

1 Answers1

1

The only things wrong with your last attempt were:

  1. you only provided file once instead of twice in the args list and
  2. you used double instead of single quotes around your script.

Using double quotes around an awk script is very, VERY rarely the right approach to doing anything.

Assuming you have these shell variables defined as shown in your question:

namespace='NameSpace'
component='customList'

Do this:

$ awk -v name="$namespace" -v comp="$component" 'NR==FNR{if ($0 ~ ("<componentName>"name":"comp"</componentName>")) for (i=-2;i<=2;i++) del[NR+i]; next} !(FNR in del)' file file
<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
        <itemInstances>
            <componentInstance>
                <componentInstanceProperties>
                    <name>collapsed</name>
                    <value>false</value>
                </componentInstanceProperties>
    ...
    </itemInstances>
    <mode>Replace</mode>
    ...

or if you prefer:

$ awk -v x="<componentName>${namespace}:${component}</componentName>" 'NR==FNR{if ($0 ~ x) for (i=-2;i<=2;i++) del[NR+i]; next} !(FNR in del)' file file
<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
        <itemInstances>
            <componentInstance>
                <componentInstanceProperties>
                    <name>collapsed</name>
                    <value>false</value>
                </componentInstanceProperties>
    ...
    </itemInstances>
    <mode>Replace</mode>
    ...

See How do I use shell variables in an awk script?.

I shortened the shell variable namespace to just name for the awk variable because namespace is a reserved word in GNU awk so you can't use it as a variable name.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Could you please reiterate why the filename should be repeated? isn't "file" a flag but a file name? – Patlatus Oct 08 '21 at 11:40