localize o arquivo xml que contém o nome da tag específico e imprima as palavras entre o nome da tag

0

podemos encontrar o tipo de arquivo xml como o seguinte

find /tmp/ -type f -name '*.xml'

mas como alterar a sintaxe para encontrar apenas xml que contenha:

<Name>some words</Name>

e imprima o que está entre:

<Name> ------ </Name>

saída esperada

some words      

exemplo - o arquivo xml contém:

<Name>files_with_extra_data</Name>

saída esperada

files_with_extra_data
    
por yael 17.01.2018 / 09:35

4 respostas

1

Uma solução simples seria usar sed:

find /tmp -name '*.xml' -exec sed -n 's/<Name>\([^<]*\)<\/Name>//p' {} +

A regex corresponde às tags e imprime o que está entre elas. Se removermos os caracteres scape, é mais fácil de ler:

s / <Name>([^<]*)</Name> /  

O parênteses corresponde a qualquer caractere que não seja "<" e é mapeado para \ 1

Como mencionado nos comentários, isso seria uma solução simples, expressões regulares não podem lidar com todas as possíveis variações de texto estruturado. Portanto, se você tiver várias linhas entre tags ou outras tags, isso não funcionará e você precisará usar um analisador xml real

    
por 17.01.2018 / 09:44
1

Para um trabalho XML simples como este, eu usaria xml2 e cut . (ou sed , ou awk ou perl ).

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | grep '/Name=' |
  cut -d '=' -f2-

ou

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | sed -n -e 's/^[^=]*\/Name=//p'

ou

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | 
  awk -F'=' '/Name=/ {$1=""; sub(/^ /,"",$0); print }'

(A chamada da função sub() na versão awk retira o espaço à esquerda depois de configurar $ 1 para "" - o awk não tem como excluir campos da linha de entrada, o melhor que você pode fazer é configurá-lo para Se preferir, split() da linha em um array, exclua o (s) campo (s) que você não deseja e, em seguida, junte o array em uma string para impressão. awk não tem uma função join() como perl , então você terá que escrever o seu próprio)

ou

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; |
  perl -F= -lane 'if (m:/Name=:) { delete @F[0]; print @F}'

xml2 converte dados formatados em XML em um formato orientado a linhas adequado para processamento com utilitários de texto orientados a linhas, como awk , ou sed ou perl e muitos outros. Ele vem com um programa 2xml correspondente, que pode converter esse formato orientado por linha de volta para XML formatado corretamente.

Para tarefas mais complicadas, eu usaria xmlstarlet

xmlstarlet é uma ferramenta de processamento XML que você pode usar para listar, consultar, extrair e modificar dados em arquivos XML.

Ambos estão disponíveis para o debian e outras distribuições Linux.

A melhor solução para IMO é usar uma linguagem como perl ou python que tenha uma biblioteca de análise XML e use isso. xmlstarlet é ótimo para trabalhar com arquivos XML no shell, mas a construção da linha de comando para pesquisas muito complicadas se torna mais trabalhosa (e muito mais difícil de ler e depurar) do que apenas escrever um script em perl ou python o emprego. Isso é em parte porque eu faço muito mais programação nessas linguagens e acho muito mais fácil trabalhar com elas ... mas principalmente porque é melhor concentrar seu esforço de aprendizado em linguagens de uso geral que podem ser usadas para uma grande variedade de tarefas em linguagens / ferramentas específicas de domínio que só podem ser usadas para uma coisa muito específica.

    
por 17.01.2018 / 09:48
0

com pcregrep :

pcregrep -rMh --include='\.xml\z' -o1 '(?s)<name>(.*?)</name>' .
    
por 17.01.2018 / 10:33
-2

Use o comando abaixo para obter o resultado mencionado. Testado e funcionou bem

Acabei de pipelinar sua saída para o delimitador awk

find /tmp/ -type f -name '*.xml' | awk -F ">" '{print $2}'  | sed "s/<.*//g"
    
por 17.01.2018 / 13:32