如何使用awk在ant构建文件的目标范围内插入一行



我需要关于使用awk(首选)、sed或perl的解决方案的帮助。该解决方案应该在bashshell脚本中集成。这是我的问题,我需要在ant构建文件目标的目标内插入一行,如下所示:

<target name="-AAAA" unless="non_AAAA_buildpackage">
              <antcall target="init"/>
              many antcall lines
</target>
<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              many antcall lines here
              The line should be inserted here  as <antcall target="ZZZZ"/>
</target>
<target name="-BBBB" unless="non_BBBB_buildpackage">
              <antcall target="init"/>
              many antcall lines here
</target>
many targets here as this is a large file

请注意,build.xml文件中有许多目标名称,但name="XXXX"总是独一无二。所有其他目标的结束分隔符与CCD_ 2相同。请注意,该行应插入该行之前。。。</target>请注意,build.xml是一个有许多目标的lagre文件,单词"name="-XXXX"是唯一的,但不是单词<strong]"-XXXX">

简单的Perl解决方案:使用一个标志$inside,它告诉您是否在所需的目标中:

perl -pe ' $inside = 1 if /<target name="-XXXX"/;
           print qq(              <antcall target="ZZZZ"/>n) if $inside and m{</target>};
           $inside = 0 if m{</target>};
         ' 1.xml

或者,使用XML::LibXML包装XML::XSH2:

open 1.xml ;
insert chunk { qq(              <antcall target="ZZZZ"/>n) } append //target[@name="-XXXX"] ;
save ;

使用GNU sed:

infile:的内容

<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              ...............
              <antcall target="YYYY"/>
              <antcall target="ZZZZ"/>  **###The line should be inserted here**
</target>
<target name="-YYYY" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              ...............
              <antcall target="YYYY"/>
              <antcall target="ZZZZ"/>  **###The line should be inserted here**
</target>

script.sed:的内容

/^<target[ t]+name="-XXXX"/,/^</target>/ {
        /^</target>/ { i
Your line                                                                                                                                                                                                                                   
        }
}

运行方式:

sed -f script.sed infile

具有以下输出:

<target name="-XXXX" unless="non_XXXX_buildpackage">                                                                                                                                                                                         
              <antcall target="init"/>                                                                                                                                                                                                       
              ...............                                                                                                                                                                                                                
              <antcall target="YYYY"/>                                                                                                                                                                                                       
              <antcall target="ZZZZ"/>  **###The line should be inserted here**                                                                                                                                                              
Your line                                                                                                                                                                                                                                    
</target>                                                                                                                                                                                                                                    
<target name="-YYYY" unless="non_XXXX_buildpackage">                                                                                                                                                                                         
              <antcall target="init"/>                                                                                                                                                                                                       
              ...............                                                                                                                                                                                                                
              <antcall target="YYYY"/>                                                                                                                                                                                                       
              <antcall target="ZZZZ"/>  **###The line should be inserted here**                                                                                                                                                              
</target>

这在sed实用程序中是可行的:

sed -i -e '/-XXXX/,/</target>/s/</target>/NEWLINEINSERTEDHEREn</target>/' infile

我们告诉sed只考虑文件中正确的<target>...</target>部分,然后用添加的行和</target> 替换</target>

使用awk执行此操作:将记录分隔符设置为</target>,您就可以定位在正确的位置:

awk -v RS='</target>' -v ORS='' -v OFS='' '
{ print }
/name="-XXXX"/ { print "              INSERTED LINE", "n" }
{ print RT }'

应该做你需要做的事。输出记录和字段分隔符应该是空的,以使空格正确。

更新

在新数据上运行上述脚本的示例:

build.xml

<target name="-AAAA" unless="non_AAAA_buildpackage">
              <antcall target="init"/>
              many antcall lines
</target>
<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              many antcall lines here
              The line should be inserted here  as <antcall target="ZZZZ"/>
</target>
<target name="-BBBB" unless="non_BBBB_buildpackage">
              <antcall target="init"/>
              many antcall lines here
</target>
many targets here as this is a large file

运行脚本:

awk -v RS='</target>' -v ORS='' -v OFS='' '
{ print }
/name="-XXXX"/ { print "tt<antcall target="ZZZZ"/>", "n" }
{ print RT }' build.xml > out.tmp

请注意,您需要转义双引号。还要注意,如果您希望在添加的行前面添加制表符,请在print语句中添加适当的金额。

out.tmp

<target name="-AAAA" unless="non_AAAA_buildpackage">
              <antcall target="init"/>
              many antcall lines
</target>
<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              many antcall lines here
              The line should be inserted here  as <antcall target="ZZZZ"/>
              <antcall target="ZZZZ"/>
</target>
<target name="-BBBB" unless="non_BBBB_buildpackage">
              <antcall target="init"/>
              many antcall lines here
</target>
many targets here as this is a large file

验证添加:

diff build.xml out.tmp

输出:

8a9                        
> <antcall target="ZZZZ"/>

编辑

这里有一个更便携的脚本版本:

awk 'BEGIN { RS="</target>"; ORS=""; OFS="" }
{ print }
/name="-XXXX"/ { print "tt<antcall target="ZZZZ"/>", "n" }
{ print RS }' build.xml > out.tmp
> cat temp
<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              <antcall target="YYYY"/>
</target>

awk解决方案:

> awk '{if($0~//target/){p="t<antcall target="ZZZZ"/>n"$0;print p}else print}' temp
<target name="-XXXX" unless="non_XXXX_buildpackage">
              <antcall target="init"/>
              <antcall target="YYYY"/>
        <antcall target="ZZZZ"/>
</target>

最新更新