使用 awk 或 sed 删除 xml 文件中包含“/”和变量替换的目标搜索字符串周围的行

Use awk or sed to remove lines in xml file around target search string containing "/" and variable substitution

我有一个 XML 文件,里面的内容如下

<?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>
    ...

我正在尝试使用 awk 从文件中删除这些行。

我尝试运行以下脚本

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 

但它不是剪切所需的行,而是在 xml 文件的开头切掉行 并产生以下输出

<?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>
    ...

我尝试使用不同形式的变量替换,就像这样

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

还有这个

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

但都不起作用。有什么方法可以让它工作吗?

更新:删除行的期望结果

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

结果文件如下所示

<?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>
    ...

您上次尝试的唯一错误是:

  1. 您在 args 列表中只提供了 file 一次而不是两次
  2. 您在脚本周围使用了双引号而不是单引号。

在 awk 脚本周围使用双引号是非常、非常少的正确方法。

假设您定义了这些 shell 变量,如您的问题所示:

namespace='NameSpace'
component='customList'

这样做:

$ awk -v name="$namespace" -v comp="$component" 'NR==FNR{if ([=11=] ~ ("<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>
    ...

或者如果您愿意:

$ awk -v x="<componentName>${namespace}:${component}</componentName>" 'NR==FNR{if ([=12=] ~ 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>
    ...

参见 How do I use shell variables in an awk script?

我将 awk 变量的 shell 变量 namespace 缩短为 name 因为 namespace 是 GNU awk 中的保留字,所以您不能使用它作为变量名。