поиск и замена на ruby ​​regex - PullRequest
8 голосов
/ 16 января 2011

У меня есть текстовое поле blob в столбце MySQL, которое содержит HTML. Мне нужно поменять часть разметки, поэтому я решил, что сделаю это в сценарии ruby. Руби здесь не имеет значения, но было бы неплохо увидеть ответ с этим. Разметка выглядит следующим образом:

<h5>foo</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>bar</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>meow</h5>
  <table>
    <tbody>
    </tbody>
  </table>

Мне нужно изменить только первый <h5>foo</h5> блок каждого текста на <h2>something_else</h2>, оставив остальную часть строки в покое.

Не могу получить правильное регулярное выражение PCRE, используя Ruby.

Ответы [ 3 ]

31 голосов
/ 16 января 2011
# The regex literal syntax using %r{...} allows / in your regex without escaping
new_str = my_str.sub( %r{<h5>[^<]+</h5>}, '<h2>something_else</h2>' )

Использование String#sub вместо String#gsub вызывает только первую замену.Если вам нужно динамически выбрать, что такое «foo», вы можете использовать интерполяцию строк в литералах регулярных выражений:

new_str = my_str.sub( %r{<h5>#{searchstr}</h5>}, "<h2>#{replacestr}</h2>" )

И снова, если вы знаете, что такое «foo», вам не нужно регулярное выражение:

new_str = my_str.sub( "<h5>searchstr</h5>", "<h2>#{replacestr}</h2>" )

или даже:

my_str[ "<h5>searchstr</h5>" ] = "<h2>#{replacestr}</h2>"

Если вам нужно запустить код для определения замены, вы можете использовать блочную форму sub:

new_str = my_str.sub %r{<h5>([^<]+)</h5>} do |full_match|
  # The expression returned from this block will be used as the replacement string
  # $1 will be the matched content between the h5 tags.
  "<h2>#{replacestr}</h2>"
end
6 голосов
/ 16 января 2011

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

Вот как это сделать с помощью Nokogiri, без каких-либо регулярных выражений:

text = <<EOT
<h5>foo</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>bar</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>meow</h5>
  <table>
    <tbody>
    </tbody>
  </table>
EOT

require 'nokogiri'

fragment = Nokogiri::HTML::DocumentFragment.parse(text)
print fragment.to_html

fragment.css('h5').select{ |n| n.text == 'foo' }.each do |n|
  n.name = 'h2'
  n.content = 'something_else'
end

print fragment.to_html

После синтаксического анализа это то, что Nokogiriвернулся из фрагмента:

# >> <h5>foo</h5>
# >>   <table><tbody></tbody></table><h5>bar</h5>
# >>   <table><tbody></tbody></table><h5>meow</h5>
# >>   <table><tbody></tbody></table>

Это после запуска:

# >> <h2>something_else</h2>
# >>   <table><tbody></tbody></table><h5>bar</h5>
# >>   <table><tbody></tbody></table><h5>meow</h5>
# >>   <table><tbody></tbody></table>
2 голосов
/ 16 января 2011

Используйте String.gsub с регулярным выражением <h5>[^<]+<\/h5>:

>> current = "<h5>foo</h5>\n  <table>\n    <tbody>\n    </tbody>\n  </table>"
>> updated = current.gsub(/<h5>[^<]+<\/h5>/){"<h2>something_else</h2>"}
=> "<h2>something_else</h2>\n  <table>\n    <tbody>\n    </tbody>\n  </table>"

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...