根据条件从 xml 文件中提取文本块

根据条件从 xml 文件中提取文本块

fqdns我想从以下文件中提取内容,但仅限于每个device位置:statusnew

<device id='10.72.48.215'>
    <address>10.72.48.215</address>
    <status>old</status>
    <fqdns>10.72.48.215</fqdns>
    <parent></parent>
    <type>Unknown</type>
    <ports>
    </ports>
    <operatingsystems>
    </operatingsystems>
</device>
<device id='10.72.48.216'>
    <address>10.72.48.216</address>
    <status>new</status>
    <fqdns>10.72.48.216</fqdns>
    <parent></parent>
    <type>Unknown</type>
    <ports>
    </ports>
    <operatingsystems>
    </operatingsystems>
</device>

因此,对于上述内容,我想获得10.72.48.216(而不是10.72.48.215)。

答案1

如果添加 XML 声明并将两个device元素包含在顶级元素中,则可以使用 XPath 处理文件:

$ cat ./248127.xml
    <device id='10.72.48.215'>
            <address>10.72.48.215</address>
            <status>old</status>
            <fqdns>10.72.48.215</fqdns>
            <parent></parent>
            <type>Unknown</type>
            <ports>
            </ports>
            <operatingsystems>
            </operatingsystems>
    </device>
    <device id='10.72.48.216'>
            <address>10.72.48.216</address>
            <status>new</status>
            <fqdns>10.72.48.216</fqdns>
            <parent></parent>
            <type>Unknown</type>
            <ports>
            </ports>
            <operatingsystems>
            </operatingsystems>
    </device>

$ ( echo '<?xml version="1.0"?><doc>'; cat ./248127.xml ; echo '</doc>' ) \
    | xpath -q -e '//device[status/text()="new"]/fqdns'
<fqdns>10.72.48.216</fqdns>

答案2

您可以使用 pcrgrep 命令来完成此操作,该命令具有多行搜索选项。

pcregrep -M "\<status.*\n.*fqdns\>$"

至于你要求的解释:

所以 -M 表示多行

\< 字符串开头的状态。我必须使用 \ 来获取 < 的含义,因为它对于 shell 来说是特殊的。

然后 。 (任意字符)后面带*表示可以重复。

\n 换行

。对于后跟 * 的字符,因为它可以重复。

然后是字符串 fqdns

并关闭

\> 又是 >,用 \ 表示含义

最后,$ 是行尾

字符串匹配称为正则表达式

https://en.wikipedia.org/wiki/Regular_expression

答案3

一个简单的grep可以做到这一点:

grep -A1 "<status>new" sample.xml 
# <status>new</status>
# <fqdns>10.72.48.216</fqdns>

仅当您的 xml 源稳定并且不会更改行的顺序时才建议这样做。 (我修改了你的示例,在第二个块中有一个“新”。)

您可以使用更多 grep 过滤以下行:

grep -A1 "<status>new" sample.xml | grep "<fqdns>" 
# <fqdns>10.72.48.216</fqdns>

sed,您可以轻松提取 IP:

sed -rn '/<status>new/{n; s/.*<fqdns>(.*)<\/fqdns>/\1/p}' sample.xml
# 10.72.48.216

它匹配<status>new并读取n外线和s替代品<fqdns>和结束标签之间的部分。这-n告诉 sed “默认情况下不打印”,“-r”允许在不屏蔽的情况下写入正则表达式(这里是 .* 周围的括号)。

相关内容