我有一个xml文件,我在这个文件中搜索一个字符串。 一旦(如果)找到该字符串,我需要能够搜索到另一个字符串的位置并输出数据。
即:
<xml>
<packet>
<proto>
<field show="bob">
</proto>
</packet>
<packet>
<proto>
<field show="rumpelstiltskin">
</proto>
</packet>
<packet>
<proto>
<field show="peter">
</proto>
</packet>
我的意见是:
show="rumpelstiltskin"
和
<packet>
我需要得到以下结果(基本上是第二个块);
<packet>
<proto>
<field show="rumpelstiltskin">
</proto>
</packet>
或
<packet>
<proto>
<field show="rumpelstiltskin">
有成千上万的(wireshark pdml转换)和show =“rumpelstilstkin”可以出现在文件的任何地方,并且该部分可以是任意大小。
之前我已经完成了这项工作,并且非常确定它可以在awk或sed oneliner中使用..任何帮助表示赞赏!
答案 0 :(得分:3)
您需要将XML视为XML并使用适当的工具。例如,稍微修改XML以使其有效:
<xml>
<packet>
<proto>
<field show="bob"/>
</proto>
</packet>
<packet>
<proto>
<field show="rumpelstiltskin"/>
</proto>
</packet>
<packet>
<proto>
<field show="peter"/>
</proto>
</packet>
</xml>
您可以像这样使用xmllint
:
xmllint --xpath '//packet[proto/field/@show="rumpelstiltskin"]' file.xml
这将匹配并打印<packet>
元素中包含<field show="rumpelstiltskin">
的所有<proto>
元素的内容。
如果您不想指定完整的层次结构,则可以使用以下内容:
xmllint --xpath '//packet[descendant::field[@show="rumpelstiltskin"]]' file.xml
答案 1 :(得分:2)
您可以使用grep
执行此操作 cat file | grep 'show="rumpelstiltskin"' -B5 | grep 'otherstring'
显然会将-B5
调整为您需要保留所需字符串的行数。
答案 2 :(得分:1)
如果您的输入非常简单,那么您需要的是:
$ awk '/<packet>/{buf=""} {buf=buf $0 RS} /rumpelstiltskin/{printf "%s",buf}' file
<packet>
<proto>
<field show="rumpelstiltskin">
或者如果您愿意:
$ awk '/<packet>/{buf="";f=0} {buf=buf $0 RS} /rumpelstiltskin/{f=1} f&&/<\/packet>/{printf "%s",buf}' file
<packet>
<proto>
<field show="rumpelstiltskin">
</proto>
</packet>
如果您想在第一次打印后停止阅读输入文件,则只需在其后添加;exit
,以便printf "%s",buf
变为printf "%s",buf; exit
。
答案 3 :(得分:0)
所以......你可以一起破解一些可以将文件作为文本文件进行基本解析的东西......
awk -v txt="rumpel" '$0=="<packet>"{s=$0; found=0; next} $0~txt{found=1} {s=s RS $0} $0=="</packet>" && found {print s}' inp.xml
为了便于说明而分解成碎片,这样做可以做到以下几点:
-v txt="rumpel"
- 设置一个在脚本中使用的变量。请注意,在此示例中,这将作为正则表达式进行评估,但如果您希望将其作为字符串进行搜索,则可以使用index()
。$0=="<packet>"{s=$0; found=0; next}
- 如果我们找到数据包的开头,请重置我们的存储变量(s
)和标记(found
)。$0~txt{found=1}
- 如果我们找到了我们要查找的文字,请设置一个标记。{s=s RS $0}
- 将当前行附加到变量$0=="</packet>" && found {print s}
- 如果我们在文本末尾找到字符串,请打印。更好的方法可能是使用本地理解XML的东西来解释XML,但仅使用sed和awk是不可能的。
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed '/<packet>/h;//!H;/rumpelstiltskin/!d;x;q' file
这会将所需的字符串存储在保留空间中,然后将其打印出来并退出。
但是要确保第一个和第二个字符串存在且彼此相邻:
sed '/<packet>/h;//!H;/rumpelstiltskin/!d;x;/<packet>.*rumpelstiltskin/!d;q' file