我有一个 XML 文件,需要附加到一组特定的标签之后。基本上文件结构如下所示:
<key>servers</key>
<dict>
... Server Details ...
</dict>
我想匹配以下几行:
<key>servers</key>
<dict>
并在 后附加指定服务器连接的 XML 块<dict>
。我已将新的 XML 块放在其自己的文本文件中,因为它相当长。
我已经考虑sed
并awk
这样做了,但我遇到了困难。我也见过使用 Perlperl
来完成此任务的示例,但我对 Perl 不太熟悉。据我了解,但sed
并不awk
擅长多行匹配。
我需要进行多行匹配的原因是因为该<dict>
标记在 XML 文件中经常使用,并且我需要在该<key>servers</key>
部分中附加一个块,而不是替换其整个内容。
答案1
你可以这样做:
awk '{print}
$0 == "<dict>" && previous == "<key>servers</key>" {
system("cat other-file.xml")
}
{previous = $0}'
答案2
sed '/keys_line_1/,/keys_line_last/{/keys_line_last/{
h;s/unique_split_point.*//;r /path/to/insert/file
x;s/.*unique_split_point//;G
}}'
sed
当涉及到需要对假设进行调整时,并不完全宽容。所做的一切sed
都是它刚刚所做的事情的直接结果,因此细节上的一个非常小的错误可能会极大地改变结果。
这样,如果没有一点点疯狂和很大的耐心,sed
脚本调试可能会是一件令人沮丧的事情,但是,考虑到这些品质,回报可能是巨大的。我高度l
如果您尝试的话,建议在此过程中尽可能多地使用ook 命令。
sed ...;l;...complicated_script...;l;...
实际上,第二次看你的问题,我认为它比我第一次想象的要容易。所有你真正需要的(我认为)是将模式空间扩大一行服务器相符。默认情况下,sed
每个周期仅缓冲一行,但命令N
、P
和D
提供对此行为的直接控制。
事实上,我相信我最初误解了这个问题 - 我以为你想将一些文本插入一行,而不是一行块。
所以你可能需要:
sed '\|<key>servers</key>|,/<dict>/N;P
/\n<dict>/!D;s/.*\n//;r /path/to/file'
这样,除了您感兴趣的那些行之外的所有行 - 从您的范围服务器通过你的词典匹配会尽快从编辑缓冲区中删除,并且您只r
在第一个之后输出目标文件词典匹配遵循您的*服务器的任何序列,并且是唯一的点文件曾经附加到输出缓冲区,直接跟随您的词典如果前面有\n
ewline,则匹配。
答案3
像这样的东西会起作用吗?
sed '\|<key>servers</key>|{n
\|<dict>| r other-file.xml
}' file.xml
答案4
由于您添加了 Perl 标签:
perl -pE 'BEGIN{
$/ = "<key>servers</key>\n<dict>\n";
$content = `cat file.xml`
}
$_.=$content' your_input_file