Issue
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>
...
Solution
The only things wrong with your last attempt were:
- you only provided
file
once instead of twice in the args list and - 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.
Answered By - Ed Morton