Count количество элементов xml из оболочки linux

Мой xml выглядит примерно так:

<elements>
<elem>
....bunch of other elements
</elem>
</elements>

Есть ли способ подсчитать количество событий тега elem в каком-либо файле xml через linux-оболочку? как с perl/python или что-нибудь, что может работать как один лайнер?

Я могу попробовать что-то вроде grep -c "elem" myfile.xml, и число, которое я получаю, делят на 2 и получаю число, есть ли что-то подобное, но одно liner?

EDIT:

Я ищу альтернативное решение grep

Ответ 1

@OP, все решения grep имеют фундаментальный "недостаток" в том, что он будет пропускать подсчеты, если теги более 1 <elem> являются одной строкой. Используйте awk для подсчета программно

awk 'BEGIN{
    totalelem=0
    totalendelem=0
}
/<elem>/{
    m = split($0,a,"<elem>") # or m = gsub(/<elem>/,"")
    totalelem+=m-1
}
/<\/elem>/{
    m = split($0,b,"</elem>") # or m = gsub("</elem>","")
    totalendelem+=m-1
}
END{
    print "Total elem tags: " totalelem
    print "Total end elem tags: " totalendelem
    # if you want to make sure each elem tag is enclosed  by corresponding end elem tag
    if ( totalelem == totalendelem ){
        print "Equal start and end tags"
    }
}
' file

Это решение предполагает, что вы знаете, как будут выглядеть ваши теги elem. Нет <elem /> или с дополнительными атрибутами.

Ответ 2

Инструмент xml_grep делает то, что вы хотите - попробуйте следующее:

xml_grep --count //elem example.xml

Эта утилита находится в пакете xml-twig-tools на Debian/Ubuntu, а здесь находится здесь.

Ответ 3

Вы также можете использовать xmllint:

xmllint --xpath "count(//elem)" myfile.xml

Ответ 4

НЕ ИСПОЛЬЗУЙТЕ РЕГУЛЯРНЫЕ ЭКСПРЕССИИ ДЛЯ ФАЙЛОВ XML/ФАЙЛОВ PARSE ИЛИ SCAN

Обязательное выражение об отказе от ответственности, здесь мое решение:

xmllint --nocdata --format myfile.xml | grep -c '</elem>'

xmllint является частью libxml, что довольно часто встречается во многих дистрибутивах linux. Это решение передает следующие ловушки regex/XML:

  • ложные пространства (-формат)
  • несколько закрывающих тегов на одной строке (-формат)
  • разделы CDATA (--nocdata)

Однако вы будете пойманы противным объявлением пространства имен и значениями по умолчанию.

Ответ 5

Лондон,

Попробуйте fgrep -c '</elem>' $filename

fgrep - стандартная утилита unix, но не уверен в Linux. Коммутатор -c означает подсчет.

Приветствия. Кит.

PS: все самое удобное для подсчета меток CLOSING, потому что у них нет атрибутов; -)

Ответ 6

grep один не поможет во всех случаях, но это простой пример для XMLStarlet. Вы можете сопоставить elem с XMLStarlet, а затем подсчитать новые строки с помощью wc -l. Новые строки минус 1 - это количество элементов.

Пример YOURFILE.xml:

<elements>
<elem>....bunch of other elements</elem><elem>....bunch of other elements</elem>
<elem>
....bunch of other elements
....bunch of other elements
</elem>
</elements>

Используйте XMLStarlet и wc-l:

echo $(($(xmlstarlet sel -t -m //elem -n YOURFILE.xml | wc -l)-1))

Выход: 3