Как заменить несколько результатов grep на str.sub в Ruby? - PullRequest
1 голос
/ 02 марта 2012

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

Моя проблема: у меня есть строка, например:

 str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n
 \t\t\t\t\t<h2>Web   Designer, Director</h2>\r\n\t\t\t\t</div>"

 # now, i want to replace the substring in <h1> </h1> and <h2> and </h2> with 
 these two string:"fooo" and "barr".

вот что я сделал:

# first, i got the exactly matched substrings of str:
r = str.scan(/(?<=<h\d>).*?(?=<\/h\d>)/)
# then, i create a hash table to set the corresponding replace strings
h = {r[0] => 'fooo', r[1] => 'barr'}
# finally, using str.gsub to replace those matched strings
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/, h)
# or like this
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) {|v| h[v]}

PS: подстрока в <h1> </h1> и <h2> </h2> не фиксирована, поэтому я должен получить эти строки ПЕРВЫМ, так чточто я могу построить хэш-таблицу.Но мне действительно не нравится приведенный выше код (потому что я написал две строки почти одинаково), я думаю, что должен быть элегантный способ сделать это.я пробовал что-то вроде этого:

str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) { ['fooo', 'barr'].each {|v| v}}

но это не сработало.потому что этот блок возвращает ['fooo', 'barr'] ВСЁ!если есть способ позволить этому блоку (или чему-то еще?) возвращать по одному элементу за раз (вернуть 'fooo' в первый раз, а затем вернуть 'barr' во второй), моя проблема будет решена!спасибо!

1 Ответ

1 голос
/ 02 марта 2012

Хотя у вас действительно нет никакого дела парсинга HTML с помощью регулярного выражения , такая библиотека, как Nokogiri , может значительно упростить эту задачу, так как вы можете напрямую модифицировать DOM, ошибка, которую make предполагает, что итератор будет выполняться только один раз для каждой замены и что блок вернет только одно значение. each фактически вернет объект, который повторяется.

Вот способ избежать всего безумия регулярных выражений:

require 'rubygems'
gem 'nokogiri'
require 'nokogiri'

str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n
 \t\t\t\t\t<h2>Web   Designer, Director</h2>\r\n\t\t\t\t</div>"

html = Nokogiri::HTML(str)

h1 = html.at_css('h1')
h1.content = 'foo'

h2 = html.at_css('h2')
h2.content = 'bar'

puts html.to_s

Если вы хотите выполнить несколько подстановок, каждая из которых получает свое значение, простой способ - просто извлечь значения из стека:

subs = %w[ foo bar baz ]

string = "x x x"

string.gsub!(/x/) do |s|
  subs.shift
end

puts string.inspect
# => "foo bar baz"

Имейте в виду, что subs потребляется здесь. Более эффективный подход заключается в увеличении некоторой переменной индекса и использовании этого значения вместо этого, но это тривиальная модификация.

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