将此标记为重复的用户错过了树木的森林,他们建议的副本不能充分回答这个问题。
以下是此字符串的示例:
<mobile_device><general><id>15</id><device_name>iPad</device_name><name>Timmy</name><asset_tag/><id>16</id><device_name>iPhone</device_name><name>Spike</name><asset_tag/></general></mobile_device>
我想以某种方式解析这个问题,结果只有:
<id>15</id><id>16</id>
因此,删除开始标记标记和结束标记标记之间未包含的所有内容,并且可能存在无限量的标记。 (虽然更现实的上限边缘情况是60,000)但是总会有至少一对标签。
我一直在玩sed,但这种语法的变化根本没用:
sed 's/.*\(<id>*</id>\).*//'
非常感谢任何指导!
答案 0 :(得分:1)
假设您的数据位于input.xml
,这里使用xmllint
和简单的XPath查询
$ cat input.xml | xmllint --xpath '//id' -
<id>15</id><id>16</id>
如果<id>...</id>
或更合适的工具不可用,您可以使用这些快速而肮脏的内容来提取xmllint
之间的信息。
$ cat input.xml | perl -pe 's/(<.?id.)/\n$1/g' | grep '^<id>' | sed -e 's/$/<\/id>/'
sed
基本上是面向行的,并且很难执行包含换行符的替换。另一方面,tr
基本上是面向字符的。如果我们使用perl
在战略位置插入换行符,那么我们可以过滤出以<id>
开头的行,并再次添加匹配的</id>
。
使用xmllint --format
也是一种很好的低复杂度方法,可以将xml转换为漂亮的xml,如果你不能正确地获得xpath查询,那么使用面向行的工具更容易分开。
$ cat input.xml | xmllint --format - | grep '^\s*<id>'
答案 1 :(得分:1)
sed
它看起来像这样......
echo "$STRING" | sed 's/<\/id>.*<id>/<\/id><id>/;s/<mobile_device><general>//;s/<device_.*_device>//;'
输出看起来像这样......
<id>15</id><id>16</id>
如何运作:
</id>
和<id>
之间的所有内容都会通过sed 's/<\/id>.*<id>/<\/id><id>/'
删除。
然后通过<mobile_device>
重新发送<general>
和sed 's/<mobile_device><general>//'
。
最后但并非最不重要的是<device_name ... mobile_device>
之间的所有内容都会通过sed 's/<device_.*_device>//'
删除。
希望这有帮助。
答案 2 :(得分:0)
您的sed
字符串看起来已接近正常工作,以下是一些调整:
sed 's=.*\(<id>.*</id>\).*=\1='
您需要选择一个未出现在命令表达式中的分隔符。 /
用于关闭</id>
,因此我使用了&#39; =&#39;代替。
然后*
将正在进行的正则表达式修改为&#34; 0或更多&#34;。你有一个>
,这意味着&#39; 0或更多关闭括号&#39;。 .
表示任何单个字符,是您真正应该使用的字符,因此带括号的表达式现在应与整个<id>
字段匹配。
最后,\1
表示您希望将第一个带括号的子表达式的结果放在结果字符串中。
这对于一般解决方案有一些限制,但如果您知道每行只有一个ID字段,则应该提供。
答案 3 :(得分:0)
awk中的另一个人。将RS
和ORS
定义为>
,并在标记<id
和</id
之间进行阅读:
$ awk 'BEGIN{RS=ORS=">"} /<id/,/<\/id/' file
<id>15</id><id>16</id>$
由于ORS
为>
,您需要使用printf
手动添加最终换行符:
$ awk 'BEGIN{RS=ORS=">"} /<id/,/<\/id/; END{printf "\n"}' file
<id>15</id><id>16</id>
$
答案 4 :(得分:0)
gawk可以更简单一些:
awk '{print RT}' RS='<id>[^>]+>'
答案 5 :(得分:-1)
如果您有gawk
$ awk -v RS='</?id>' -v ORS='' '!(NR%2) {print pRT $0 RT}
{pRT=RT}
END {printf "\n"}' file
当然,您可以对打印语句中的标签进行硬编码并删除RT。