Encontre arquivos XML com valores específicos

1

Eu tenho uma pasta com arquivos XML de ~ 10K. Cada um deles se parece com isso:

...
<object>
<name>Cat</name>
</object>
<object>
<name>Cow</name>
</object>
...

O name inclui pessoa, gato, cachorro, vaca, ... Eu quero escolher os únicos arquivos xml com gato e / ou cachorro. Como posso fazer isso?

    
por Huyen 18.05.2018 / 07:06

3 respostas

1

Para obter todos os valores de Cat ou Dog do nó name em um documento XML como o seu, use xmlstarlet da seguinte forma:

xmlstarlet sel -t -v '//object/name[text() = "Cat" or text() = "Dog"]' file.xml

Isso geraria as palavras Cat e Dog como saída se elas existirem no documento como os valores de um nó-filho object do name . Essa operação seria difícil de acertar com grep caso haja outros name nós que não sejam nós filhos para object nós, ou se alguns name nós tiverem atributos etc.

Infelizmente, xmlstarlet não sai com um status de saída diferente de zero se não encontrar nada no arquivo de entrada XML, por isso precisamos adicionar um grep no final para verificar se obteve alguma saída (isso será usado na próxima etapa):

xmlstarlet sel -t -v '//object/name[text() = "Cat" or text() = "Dog"]' file.xml | grep '.'

Em seguida, podemos executar isso em todos os arquivos 10k, embora find :

find . -type f -name '*.xml' -exec sh -c '
    xmlstarlet sel -t -v "//object/name[text() = \"Cat\" or text() = \"Dog\"]" "$1" |
    grep -q "."' sh {} ';' -print

Isso primeiro encontrará todos os arquivos regulares dentro ou abaixo do diretório atual cujos nomes terminam com .xml . Para cada arquivo, xmlstarlet é executado para extrair as sequências Cat e Dog dos nós XML corretos, e grep é usado para verificar se xmlstarlet encontrou alguma coisa. A execução de grep com sua opção -q torna o utilitário silencioso, mas sairá com o status de saída apropriado, dependendo se ele correspondeu a algo ou não.

Se grep encontrou alguma coisa, find imprime o nome do caminho do arquivo que continha os dados.

    
por 18.05.2018 / 07:59
1

O código a seguir é baseado em GNU grep

Como você disse, todos os arquivos são assim, então você pode usar o grep

para gato ou cachorro, use

grep -l '<name>\(Cat\|Dog\)</name>' *

para que o gato e o cão estejam presentes, use

grep -l '<name>Cat</name>' * | xargs grep -l '<name>Dog</name>'

e se você quiser uma pesquisa sem distinção entre maiúsculas e minúsculas, adicione a opção -i ao grep

-l - esta opção imprimirá apenas o nome do arquivo que tiver correspondência

Com regex normal, os caracteres ( , | e ) precisam ser escapados, por isso escapei deles

    
por 18.05.2018 / 07:16
0

Se você tiver muitos arquivos, considere o uso de ferramentas de indexação como Beagle, Tracker, vislumbres ou similares.

Exemplo:

$ glimpseindex -H .  MyDir
$ glimpse -l  -H .  'cat;dog'     

para obter os arquivos contendo cad e dog

    
por 18.05.2018 / 10:32