Рубиновая замена нескольких строк - PullRequest
65 голосов
/ 15 ноября 2011
str = "Hello☺ World☹"

Ожидаемый результат:

"Hello:) World:("

Я могу сделать это: str.gsub("☺", ":)").gsub("☹", ":(")

Есть ли другой способ сделать это за один вызов функции?,Что-то вроде:

str.gsub(['s1', 's2'], ['r1', 'r2'])

Ответы [ 7 ]

108 голосов
/ 15 ноября 2011

Начиная с Ruby 1.9.2, String#gsub принимает хэш в качестве второго параметра для замены соответствующими ключами. Вы можете использовать регулярное выражение, чтобы сопоставить подстроку, которую нужно заменить, и передать хэш для значений, подлежащих замене.

Как это:

'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"
'(0) 123-123.123'.gsub(/[()-,. ]/, '')    #=> "0123123123"

В Ruby 1.8.7 вы бы достигли того же с блоком:

dict = { 'e' => 3, 'o' => '*' }
'hello'.gsub /[eo]/ do |match|
   dict[match.to_s]
 end #=> "h3ll*"
36 голосов
/ 15 ноября 2011

Настройте таблицу сопоставления:

map = {'☺' => ':)', '☹' => ':(' }

Затем создайте регулярное выражение:

re = Regexp.new(map.keys.map { |x| Regexp.escape(x) }.join('|'))

И, наконец, gsub:

s = str.gsub(re, map)

Если вы застряли на 1,8 земле, тогда:

s = str.gsub(re) { |m| map[m] }

Вам понадобится Regexp.escape, если все, что вы хотите заменить, имеет особое значение внутрирегулярное выражениеИли, благодаря steenslag, вы можете использовать:

re = Regexp.union(map.keys)

, и за вас позаботятся о цитировании.

35 голосов
/ 15 ноября 2011

Вы можете сделать что-то вроде этого:

replacements = [ ["☺", ":)"], ["☹", ":("] ]
replacements.each {|replacement| str.gsub!(replacement[0], replacement[1])}

Возможно, есть более эффективное решение, но это по крайней мере делает код немного чище

18 голосов
/ 26 марта 2013

Поздно к вечеринке, но если вы хотите заменить некоторые символы одним, вы можете использовать регулярное выражение

string_to_replace.gsub(/_|,| /, '-')

В этом примере gsub заменяет подчеркивания (_), запятые (,) или () с тире (-)

4 голосов
/ 24 мая 2017

Вы также можете использовать tr для замены нескольких символов в строке одновременно,

Например, заменить "h" на "m" и "l" на "t"

"hello".tr("hl", "mt")
 => "metto"

выглядит просто, аккуратно и быстрее (хотя разница не большая), чем gsub

puts Benchmark.measure {"hello".tr("hl", "mt") }
  0.000000   0.000000   0.000000 (  0.000007)

puts Benchmark.measure{"hello".gsub(/[hl]/, 'h' => 'm', 'l' => 't') }
  0.000000   0.000000   0.000000 (  0.000021)
4 голосов
/ 25 февраля 2013

Еще один простой и удобный для чтения способ заключается в следующем:

str = '12 ene 2013'
map = {'ene' => 'jan', 'abr'=>'apr', 'dic'=>'dec'}
map.each {|k,v| str.sub!(k,v)}
puts str # '12 jan 2013'
1 голос
/ 13 февраля 2019

На основании ответа Нарена выше , я бы пошел с

tr = {'a' => '1', 'b' => '2', 'z' => '26'}
mystring.gsub(/[#{tr.keys}]/, tr)

Так 'zebraazzeebra'.gsub(/[#{tr.keys}]/, tr) возврат "26e2r112626ee2r1"

...