Как мне получить предметы из StringScanner?

Я использую StringScanner Руби для нормализации текста на английском языке.

def normalize text
  s = ''
  ss = StringScanner.new text
  while ! ss.eos? do
    s += ' ' if ss.scan(/\s+/)             # mutiple whitespace => single space
    s += 'mice' if ss.scan(/\bmouses\b/)   # mouses => mice
    s += '' if ss.scan(/\bthe\b/)          # remove 'the'
    s += "#$1 #$2" if ss.scan(/(\d)(\w+)/) # should split 3blind => 3 blind
  end
  s
end

normalize("3blind the   mouses")  #=> should return "3 blind mice"

Вместо этого я просто получаю " mice",

StringScanner#scan не захватывает (\d) а также (\w+),

2 ответа

Решение

Для доступа к захваченному StringScanner (в Ruby 1.9 и выше) вы используете StringScanner#[]:

  s += "#{ss[1]} #{ss[2]}" if ss.scan(/(\d)(\w+)/) # splits 3blind => 3 blind

В Ruby 2.1 вы должны иметь возможность захватывать по имени (см. Ссылку Питера Альфвина)

  s += "#{ss[:num]} #{ss[:word]}" if ss.scan(/(?<num>\d)(?<word>\w+)/)

Примечание: первая версия этого / моего ответа была совершенно неосновной, согласно ветке комментариев. Извиняюсь.

Основываясь на экспериментах и ​​обзоре http://ruby-doc.org/stdlib-1.9.2/libdoc/strscan/rdoc/StringScanner.html, кажется, что StringScanner не устанавливает переменные соответствия $1, $2и т. д., так что последний s += ... заявление только добавляет пробел к s,

Смотря на strscan.c похоже, что действительно нет поддержки для предоставления захваченной информации о совпадении, но я нашел https://www.ruby-forum.com/topic/4413436, который, похоже, является предпринимаемой попыткой своего рода реализовать это.

Другие вопросы по тегам