我需要关于使用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>