我有一个如下所示的 XML 文件:
<id>456</id>
<root>
<value>1</value>
<intNum>2</intNum>
</root>
<root>
<eulav>1</eulav>
<muNtni>2</muNtni>
</root>
我想记住<id>456</id>
然后这样做:
sed 's/\<root\>/\
\<root\>
$herecomestheid
基本上,它的作用就是替换<root>
为<root>\n<id>456</id>
.\n
在这种情况下意味着换行。我已经知道了,但我遇到的问题是记住<id>456</id>
并保留它以供以后使用。
我尝试了这个(这显然不起作用):
sed -i '' 's/\<root\>/\
\<root\>\
\<id\>.\<\/id\>/g'
我尝试做这样的事情:
cat file.xml | grep '\<id\>*\<\/id\>'
并尝试将 grep 输出放入变量中。这显然也不起作用。
编辑: <id>*</id>
应该在根目录下。
答案1
将 XML 作为文本处理通常不是一个可靠的解决方案,但如果您坚持这样做,那么您也许可以使用 sed保留空间 例如
sed -e '/<id>[0-9]*<\/id>/h' -e '/<root>/{x;p;x;}' file.xml
答案2
sed -e :b -e '$!{N;\|<id>.*\n<root>|!bb
};do what ever you want to do with all of those lines now....'
我同意 Steeldriver 的观点,认为h
oldspace 可能是最好的选择,但还有其他选择。有时我们懒得管理两个缓冲区 - 或者,这通常是我的问题 - 我们已经是管理两个缓冲区。上面的代码片段在模式空间中堆叠行。只要总是出现在<id>
标签之间,在移动到第 2 行之前,它总是会用所需的数据块递归地填充模式空间 -也就是说,只要缓冲区不同时崩溃,它就会这样做 - 但现在这是一件相当困难的事情。
另外,回到h
旧的空间问题,电子x
改变确实如此交换 h
旧的和图案的空间。使用它一次会将模式缓冲区渲染为h
旧缓冲区,反之亦然。这种效应在线路周期中仍然存在。我所做的通常是读取文件,直到到达起始行,执行初步编辑,然后交换并保持H
旧状态,直到得到另一个。当我的脚本交换回来时,它会落后一个块 - 在我打开的最后一个标记处,加上H
同时的所有字段。这是一种简单的方法,可以在必要时仅缓冲必要的量。
因此,实现您想要的循环的另一种方法是:
sed -e '/<id>/h;//!H;/<root>/!{$!d' -e '};x...'
从那时起,您的模式空间就是H
旧空间,反之亦然。h
旧遗嘱覆盖 h
每当使用旧空间时,它都会与当前模式空间一起使用 - 因此上面的示例<id>
每次都会用一行开始一个新的缓冲区。!H
追加H
旧空间的所有中间行均跟随一个\n
ewline 字符。一旦当前行安全地进入并开始下一个行循环,就会删除不是最后一行$!d
的每一行上的模式空间,因此更改仅发生在整个块正在等待您的匹配上。!
$
H
x
<root>
请记住,在您的最后块,您的标记可能是最后一行,以防它与<root>
匹配项不同。
但...
根据您的编辑,我不认为您有任何理由无法逃脱:
sed '/<id>/h;//d;\|</root>|G
' <<\INPUT
unimportant 1
<id> number 1 </id>
<root> sub text
more text
more text
</root>
<root> sub text as well
and more text
and more text
</root>
unimportant 2
<id> number 2 </id>
<root> sub text
more text
more text
</root>
<root> sub text
and more text
and more text
</root>
INPUT
有<id>
线路是h
字段(再次:覆盖h
旧空间)然后d
从输出中删除。当</root>
发生匹配时,在行周期末尾自动打印结果之前,sed
G
将旧空间附加到模式空间,如下所示:h
unimportant 1
<root> sub text
more text
more text
</root>
<id> number 1 </id>
<root> sub text as well
and more text
and more text
</root>
<id> number 1 </id>
unimportant 2
<root> sub text
more text
more text
</root>
<id> number 2 </id>
<root> sub text
and more text
and more text
</root>
<id> number 2 </id>
答案3
使用的解决方案awk
是
awk '/<id>/{id=$0}/<root>/{print id}1' file.xml
如果您不想打印该<id>
行,可以通过添加 来跳过该行next
。
awk '/<id>/{id=$0;next}/<root>/{print id}1' file.xml