从xml中提取数据sed或grep或awk

时间:2018-03-14 20:23:26

标签: xml csv awk sed grep

我有以下xml。我需要将IP地址,协议和端口提取到具有相应列名的CSV文件中。

<rule family="ipv4">
<source address="10.XXX.XX.XX"/>
<port protocol="tcp" port="22"/>
<log prefix="ber_" level="warning">
<limit value="1/m"/>
</log>
<accept/>
</rule>
<rule family="ipv4">
<source address="10.XXX.XX.XXX"/>
<port protocol="udp" port="1025"/>
<log prefix="ber_" level="warning">
<limit value="1/m"/>
</log>
<accept/>

我可以使用grep或sed grep IP地址或端口grep -Eo "([0-9]{1,3}[\.]){3}[0-9]{1,3}"但是我需要它作为CSV文件中的列。

IPAddress协议端口。实现这一目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

不要'使用正则表达式来解析html / xml,而是使用真正的解析器(使用):

更正了错误的输入xml文件:

<root>
    <rule family="ipv4">
        <source address="10.XXX.XX.XX"/>
        <port protocol="tcp" port="22"/>
        <log prefix="ber_" level="warning">
            <limit value="1/m"/>
        </log>
    </rule>
    <rule family="ipv4">
        <source address="10.XXX.XX.XXX"/>
        <port protocol="udp" port="1025"/>
        <log prefix="ber_" level="warning">
            <limit value="1/m"/>
        </log>
    </rule>
</root>

代码:

xmlstarlet sel -t -v '//source/@address | //port/@protocol | //port/@port' file |
perl -pe '$. % 3 != 0 && s/\n/,/g;END{print "\n"}'

输出:

10.XXX.XX.XX,tcp,22
10.XXX.XX.XXX,udp,1025

理论:

根据编译理论,无法使用基于finite state machine的正则表达式解析HTML。由于HTML的层次结构,您需要使用pushdown automaton并使用LALR等工具操作YACC语法。

中的realLife©®™日常工具:

您可以使用以下其中一项:

xmllint

xmlstarlet

saxon-lint(我自己的项目)

检查:Using regular expressions with HTML tags

答案 1 :(得分:0)

缺少xml工具,这是一个脆弱的awk解决方案

1$ awk -v RS='</rule>' '
       {for(i=1;i<=NF;i++) 
          if($i~/^(address|protocol|port)/) 
            {split($i,a,"\""); printf "%s", a[2] (++c%3?FS:ORS)}}' file

10.XXX.XX.XX tcp 22
10.XXX.XX.XXX udp 1025