1

我需要有关使用 awk(首选)、sed 或 perl 的解决方案的帮助。该解决方案应该集成在 bash shell 脚本中。这是我的问题,我需要在 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"始终是唯一的。所有其他目标的结束分隔符与</target>. 请注意,该行应插入该行之前...</target> 请注意 build.xml 是一个包含许多目标的 lagre 文件,单词“name="-XXXX"是唯一的,但不是单词“-XXXX”

4

5 回答 5

1

简单的 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 ;
于 2012-08-22T08:56:27.727 回答
1

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>
于 2012-08-22T08:59:37.920 回答
1

这可以通过sed实用程序实现:

sed -i -e '/-XXXX/,/<\/target>/s/<\/target>/NEWLINEINSERTEDHERE\n<\/target>/' infile

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

于 2012-08-22T09:01:09.453 回答
1

这样做awk:将记录分隔符设置为,</target>然后您将锚定在正确的位置:

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

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

更新

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

构建.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 "\t\t<antcall target=\"ZZZZ\"/>", "\n" }
{ print RT }' build.xml > out.tmp

请注意,您需要转义双引号。另请注意,如果您想在添加的行前面添加制表符,请在print语句中添加适当的数量。

输出.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 "\t\t<antcall target=\"ZZZZ\"/>", "\n" }
{ print RS }' build.xml > out.tmp
于 2012-08-22T09:17:14.623 回答
0
> 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>
于 2012-08-22T09:18:21.710 回答