1

У меня есть несколько тысяч (правильно сформированных) файлов XML следующего шаблона:

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

Мне нужно получить список тех утверждений, для которых текстовое содержимое тела занимает более 10 строк. Если не считать написания скрипта Python для этого, есть ли простой способ использовать grep или другие стандартные инструменты для просмотра каждого файла и возврата операторов, которые занимают много строк? По крайней мере, я был бы счастлив с чем-то, что возвращало бы список имен файлов, для которых есть одно такое утверждение.

2 ответа2

2

Если не использовать настоящую библиотеку xml и / или awk / perl / python / ruby, это довольно близко к тому, что вы хотите (если я вас правильно понял), просто используя обычные команды bash.

Обратите внимание, что это действительно относится к используемым XML-файлам и не должно поощряться как анализатор / сплиттер общего назначения.

Вам понадобится выходной каталог для разделенных файлов. Я использовал /tmp /out для этого примера:

mkdir -p /tmp/out 

Вам придется очищать /tmp/out перед каждым запуском. В противном случае вы получите результат, который не имеет смысла.

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. кошка XML-файлов
  2. Используйте egrep для удаления ненужных строк
  3. разделить ввод на несколько файлов на основе вашего примера «имя оператора»
  4. результаты цикла
  5. считать строки для каждого файла и требовать, чтобы он был больше 10
  6. вывод на печать имени файла
  7. печатать выходные строки

Как я уже сказал, это не означает, что это обычный xml-сплиттер, но его следует рассматривать как пример различных команд оболочки.

Примечание: знак '\' с последующим переводом строки означает, что строка продолжается без разрывов строки. Это просто облегчает чтение.

1

Я могу делать только Ruby с установленным Gem nokogiri . Я не думаю, что использование grep было бы таким простым, но, возможно, у кого-то есть лучшее решение. Синтаксис:

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

Так, например:

ruby find.rb . 10

Это перечислит все .xml документы, которые

  • содержать statement с
  • с текстом CDATA
  • это в body
  • который содержит более <number-of-lines> строк текста (>, не ≥)

Там нет обработки исключений, хотя.


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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .