我有一个xml文件,我想找到第二次出现的字符串,然后从字符串中删除第二行。这是外观的示例:
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>sysad</role>
</application>
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>tester</role>
</application>
这是我想要的样子:
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>sysad</role>
</application>
.
.
.
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
</const>
<role>tester</role>
</application>
参数标记应从第二个实例中完全删除
我正在搜索tester.update
,然后尝试删除第二次出现tester.update时向下两行的行
我尝试做类似的事情:
sed -i 'tester.update/{p;N;d}' file.txt
但这会从tester.update.
的两个实例中删除第二行
非常感谢您提前提供帮助
答案 0 :(得分:1)
使用XML解析器,Perl解决方案会简单得多。这是Mojo::DOM的样子,它使用CSS rules查找标签:
use strict;
use warnings;
use Mojo::DOM;
use open ':std', ':encoding(UTF-8)';
my $xml = do { local $/; <> };
my $dom = Mojo::DOM->new->xml(1)->parse($xml);
$dom->at('application:nth-of-type(2) > app > const')->content('');
print $dom->to_string;
结果:
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>sysad</role>
</app></application>
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const />
<role>tester</role>
</app></application>
(它甚至修复了<app>
缺少的结束标记)
答案 1 :(得分:0)
这可能对您有用(GNU sed):
sed -Ei '/tester.update/{x;s/^/x/;/^x{2}$/{;x;n;n;d};x}' file
每次看到字符串tester.update
时,请在保持空间中增加一个计数器。如果该计数器包含2,请交换回当前行,将其打印出来并显示下一行,然后删除下一行。
答案 2 :(得分:0)
假设您没有XML解析器:
sed用于在单独的行上进行s / old / new,仅此。对于其他任何事情,您都应该使用awk,例如在每个UNIX盒子上的任何外壳中的任何awk中,您都可以清楚而简单地执行以下操作:
$ awk '/tester.update/{if (++cnt==2) skip=NR+2} NR!=skip' file
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>sysad</role>
</application>
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
</const>
<role>tester</role>
</application>
是否要找到tester.update
的第127次而不是第二次?只需将cnt==2
更改为cnt==127
。想要删除找到的第93行而不是第2行吗?只需将skip=NR+2
更改为skip=NR+93
。尝试对sed解决方案进行微不足道的更改(或其他任何更改!)。
为简洁起见,我喜欢吗?您也可以在awk中为了简洁而牺牲清晰度:
$ awk '/tester.update/&&++c==2{s=NR+2}NR!=s' file
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
<argument>READ_ONLY</argument>
</const>
<role>sysad</role>
</application>
<application>
<app>
<Name>Tester</Name>
<Class>tester.update</Class>
<const>
</const>
<role>tester</role>
</application>
但重要的是您不必,最后,如果您喜欢使用-i
就地编辑GNU sed,则GNU awk与-i inplace
相同。 / p>