труба одна длинная линия как несколько строк - PullRequest
3 голосов
/ 02 июля 2011

Скажем, у меня есть несколько XML-файлов, которые не содержат символов новой строки, но в основном содержат длинный список записей, разделенных </record><record>

Если бы разделитель был </record>\n<record>, я мог бы сделать что-то вроде cat *.xml | grep xyz | wc -l, чтобы подсчитать количество интересующих записей, потому что cat выдаст записи по одной на строку.

Есть ли способ написать SOMETHING *.xml | grep xyz | wc -l, где SOMETHING может выводить записи по одной на строку? Я попытался использовать awk для этого, но не смог найти способ избежать потоковой передачи всего файла в память.

Надеюсь, вопрос достаточно ясен:)

Ответы [ 4 ]

5 голосов
/ 02 июля 2011

Это немного уродливо, но это работает:

sed 's|</record>|</record>\
|g' *.xml | grep xyz | wc -l

(Да, я знаю, я мог бы сделать его немного короче, но только ценой ясности.)

2 голосов
/ 02 июля 2011

Здесь другой подход, использующий xsltproc , grep и wc .Предупреждение: я новичок в XSL, поэтому могу быть опасным :-).Вот мой файл count_records.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text" />      <!-- Output text, not XML -->
  <xsl:template match="record">     <!-- Search for "record" node -->
    <xsl:value-of select="text()"/> <!-- Output: contents of node record -->
    <xsl:text>                      <!-- Output: a new line -->
    </xsl:text>
  </xsl:template>

</xsl:stylesheet>

На моем Mac я нашел инструмент командной строки с именем xsltproc , который читает инструкции из XSL-файла и обрабатывает XML-файлы.Таким образом, команда будет иметь следующий вид:

xsltproc count_records.xsl *.xml | grep SEARCH_STRING | wc -l
  • Команда xsltproc отображает текст в каждом узле, по одной строке за раз
  • grepКоманда отфильтровывает интересующий вас текст
  • Наконец, команда wc производит счет
2 голосов
/ 02 июля 2011

Если в вашем теле записи нет символов, таких как < или / или >, то вы можете попробовать это:

grep -E -o 'SEARCH_STRING[^<]*</record>' *.xml| wc -l

или

grep -E -o 'SEARCH_STRING[^/]*/record>' *.xml| wc -l

или

grep -E -o 'SEARCH_STRING[^>]*>' *.xml| wc -l
1 голос
/ 03 июля 2011

Вы также можете попробовать xmlstarlet для файлов размером с гиг:

# cf. http://niftybits.wordpress.com/2008/03/27/working-with-huge-xml-files-tools-of-the-trade/

xmlstarlet sel -T -t -v "count(//record[contains(normalize-space(text()),'xyz')])" -n *.xml | 
    awk '{n+=$1} END {print n}'

xmlstarlet sel -T -t -v "count(//record[contains(normalize-space(text()),'xyz')])" -n *.xml | 
    paste -s -d '+' /dev/stdin | bc
...