Как подсчитать подстроку, используя регулярное выражение в ruby? - PullRequest
1 голос
/ 28 апреля 2011

У меня очень большой XML-файл, который я загружаю в виде строки так что мой XML крутит как

<publication ID="7728" contentstatus="Unchanged" idID="0b000064800e9e39">
<volume contentstatus="Unchanged" idID="0b0000648151c35d">
  <article ID="5756261" contentstatus="Changed" doi="10.1109/TNB.2011.2145270" idID="0b0000648151d8ca"/>
</volume>

Я хочу посчитать количество вхождений в строку

article ID="5705641" contentstatus="Changed"

как я могу преобразовать идентификатор в регулярное выражение

Вот что я пытался сделать

searchstr = 'article ID=\"/[1-9]{7}/\" contentstatus=\"Changed\"'
count = ((xml.scan(searchstr).length)).to_s
puts count

Пожалуйста, дайте мне знать, как мне этого добиться?

Спасибо

Ответы [ 4 ]

4 голосов
/ 28 апреля 2011

Я собираюсь выйти на конечность и догадаться, что вы новичок в Ruby.Во-первых, нет необходимости преобразовывать счетчик в строку, чтобы поместить его.Автоматически вызывает to_s для всего, что вы ему отправляете.

Во-вторых, редко бывает неплохо обрабатывать XML с помощью обработки строк.Я настоятельно рекомендую вам использовать полноценный синтаксический анализатор XML, такой как Nokogiri.

Тем не менее, вы не можете встраивать регулярные выражения в такую ​​строку.Вся строка запроса должна быть регулярным выражением.

Что-то вроде

/article ID="[1-9]{7}" contentstatus="Changed"/

Кавычки не являются специальными символами в регулярном выражении, поэтому вам не нужно их экранировать.

Если у вас есть сомнения по поводу регулярных выражений в Ruby, я рекомендую проверить Rubular.com .

И еще раз, я не могу подчеркнуть, что я действительно не одобряюпытаясь манипулировать XML с помощью регулярных выражений.Nokogiri сделает работу с XML в миллиард раз проще и надежнее.

2 голосов
/ 29 апреля 2011

Nokogiri - мой рекомендуемый парсер Ruby XML.Он очень надежный и, вероятно, сейчас является стандартом для языка.

Я добавил еще две «статьи», чтобы показать, как легко можно находить содержимое и манипулировать им, не полагаясь на регулярное выражение.

require 'nokogiri'

xml =<<EOT
<publication ID="7728" contentstatus="Unchanged" idID="0b000064800e9e39">
<volume contentstatus="Unchanged" idID="0b0000648151c35d">
  <article ID="5756261" contentstatus="Changed"   doi="10.1109/TNB.2011.2145270" idID="0b0000648151d8ca"/>
  <article ID="5756262" contentstatus="Unchanged" doi="10.1109/TNB.2011.2145270" idID="0b0000648151d8ca"/>
  <article ID="5756263" contentstatus="Changed"   doi="10.1109/TNB.2011.2145270" idID="0b0000648151d8ca"/>
</volume>
EOT

doc = Nokogiri::XML(xml)
puts doc.search('//article[@contentstatus="Changed"]').size.to_s + ' found'

puts doc.search('//article[@contentstatus="Changed"]').map{ |n| "#{ n['ID'] } #{ n['doi'] } #{ n['idID'] }" }

>> 2 found
>> 5756261 10.1109/TNB.2011.2145270 0b0000648151d8ca
>> 5756263 10.1109/TNB.2011.2145270 0b0000648151d8ca

Проблема использования регулярных выражений с HTML или XML заключается в том, что они действительно легко сломаются, если XML-код изменится, или если ваш XML получен из разных источников или искажен.Regex никогда не был предназначен для решения такого рода проблем, но парсер был.Вы можете иметь XML с концами строк после каждого тега или вообще без него, и парсер на самом деле не будет заботиться, пока XML правильно сформирован.Хороший парсер, такой как Nokogiri, может даже делать исправления, если XML сломан, чтобы попытаться понять это, но

2 голосов
/ 28 апреля 2011

Если XPath является опцией, это предпочтительный способ выбора элементов XML.Вы можете использовать селектор:

//article[@contentstatus="Changed"]

или, если возможно:

count(//article[@contentstatus="Changed"])
1 голос
/ 28 апреля 2011

Ваша текущая строка выглядит для меня почти идеально, просто удалите ошибочную / из чисел:

searchstr = 'article ID=\"[1-9]{7}\" contentstatus=\"Changed\"'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...