Localizando texto CDATA de múltiplas linhas em um monte de arquivos XML (possivelmente usando grep)

1

Eu tenho vários milhares de arquivos XML (bem formados) do seguinte modelo:

<?xml version="1.0" ?>
<queries>
  <statement name="foobar">
    <body><![CDATA[
      Several lines
      worth of
      text goes
      in here 
    ]]></body>
  </statement>
  <statement name="whatever">
    [... snip ...]
  </statement>
</queries>

Eu preciso obter uma lista dessas declarações para as quais o conteúdo de texto do corpo abranja mais de 10 linhas. Além de escrever um script python para fazer isso, existe uma maneira simples de usar o grep ou outras ferramentas padrão para examinar cada arquivo e retornar as instruções que abrangem muitas linhas? No mínimo, eu ficaria feliz com algo que retornaria uma lista de nomes de arquivos para os quais há uma declaração desse tipo.

    
por Fred 22.11.2011 / 21:27

2 respostas

2

Curta de usar uma biblioteca xml real e / ou awk / perl / python / ruby, isso é bem parecido com o que você quer (se eu entendi direito) apenas usando comandos bash comuns.

Por favor, note que isso é realmente específico para arquivos xml usados e não deve ser incentivado como um analisador / divisor xml de propósito geral.

Você precisará do diretório de saída dos arquivos divididos. Eu usei / tmp / out para este exemplo:

mkdir -p /tmp/out 

Você terá que limpar /tmp/out antes de cada execução. Caso contrário, você obterá resultados que não fazem sentido.

cat /path_to_xml_files/*.xml | \
egrep -v '<?xml version="1.0" \?>|<queries>|</queries>' | \
csplit -q -z - '/statement name/' '{*}' --prefix=/tmp/out/splitout- && \
for x in /tmp/out/splitout-* ; do \
[[ $(wc -l "$x"|cut -d" " -f 1) -gt 10 ]] && \
echo "$x" && \
cat "$x" ; \
done
  1. cat os arquivos xml
  2. Use egrep para remover linhas indesejadas
  3. divide a entrada em vários arquivos com base no seu exemplo "nome da instrução"
  4. resultados de loop
  5. conta linhas para cada arquivo e exige que ele seja maior que 10
  6. nome do arquivo de saída de impressão
  7. imprimir linhas de saída

Como eu disse, isso não deve ser um splitter xml geral, mas deve ser tratado como um exemplo de comandos de shell diferentes.

Nota: '\' -sign seguido por quebra de linha significa que a linha continua sem quebras de linha. Isso apenas facilita a leitura.

    
por 17.01.2012 / 08:15
1

Eu só posso fazer Ruby, com o nokogiri Gem instalado. Eu não acho que usar o grep seria tão simples aqui, mas talvez alguém tenha uma solução melhor. A sintaxe é:

ruby scriptname.rb <directory> <number-of-lines>

Então, por exemplo:

ruby find.rb . 10

Isso listará todos os .xml documentos que

  • contém statement s
  • com um CDATA text
  • que está em body
  • que tem mais de <number-of-lines> linhas de texto (& gt ;, não ≥)

Não há tratamento de exceção.

require 'nokogiri'
dir, lines = ARGV
@result = []
Dir.glob("#{dir}/*.xml") do |entry|
  Nokogiri::XML(File.open(entry)).xpath("//statement/body").each { |b| (@result << entry and break) if b.text.lines.count > (2+lines.to_i) }
end
puts @result
    
por 22.11.2011 / 22:21

Tags