extrai blocos de texto do arquivo xml com uma condição

2

Desejo extrair o conteúdo de fqdns do seguinte arquivo, mas somente para cada device , em que status é new :

    <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>

Então, acima, quero obter 10.72.48.216 (e não 10.72.48.215 ).

    
por Hai Le 08.12.2015 / 16:51

3 respostas

3

Se você adicionar uma declaração XML e colocar os dois elementos device em um elemento de nível superior, poderá processar seu arquivo com 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>
    
por 08.12.2015 / 17:11
1

Você pode fazer isso com um comando pcrgrep, que tem uma opção para pesquisa de múltiplas linhas.

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

Quanto à explicação que você solicitou:

So -M para multilinhas

\ < status para o início da string. Eu tenho que usar \ para tirar o significado de < como é especial para o shell.

Então. (qualquer caractere) seguido por * significa que pode ser repetido.

\ n para uma nova linha

para um caracter seguido por * como pode ser repetido.

então a string fqdns

e para fechar

\ > que novamente é & gt ;, com \ para ter o significado

e finalmente, $ é o fim da linha

A correspondência de strings é conhecida como regexp

link

    
por 08.12.2015 / 17:15
1

Um simples grep pode ajudar:

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

que é apenas recomendado se a origem do xml for estável e não alterar a ordem das linhas. (Eu modifiquei o seu exemplo para ter um 'novo' no segundo bloco.)

Você pode filtrar a seguinte linha com mais grep:

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

Com sed , você pode facilmente extrair apenas o IP:

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

Corresponde a <status>new e lê a linha ext n e s ubstitutes <fqdns> e a tag final com a parte em betweeen. O -n informa ao sed para 'sem impressão por padrão', o '-r' é para permitir que expressões regulares, aqui as parens around. *, Sejam escritas sem mascarar.

    
por 08.12.2015 / 17:10