ruby параметризованное регулярное выражение - PullRequest
0 голосов
/ 07 мая 2010

У меня есть строка типа "{some | words | are | here}" или "{another | set | of | words}"

Таким образом, в общем случае строка состоит из открывающей фигурной скобки, словаразделенные трубкой и закрывающей фигурной скобкой.

Какой самый эффективный способ получить выбранное слово этой строки?

Я хотел бы сделать что-то вроде этого:

@my_string = "{this|is|a|test|case}"
@my_string.get_column(0) # => "this"
@my_string.get_column(2) # => "is"
@my_string.get_column(4) # => "case"

Что должен содержать метод get_column?

1 Ответ

2 голосов
/ 07 мая 2010

Так что это решение, которое мне сейчас нравится:

class String
  def get_column(n)
    self =~ /\A\{(?:\w*\|){#{n}}(\w*)(?:\|\w*)*\}\Z/ && $1
  end
end

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

Объяснение регулярного выражения:

  • \A - начало строки, а \Z - конец, поэтому это регулярное выражение соответствует строке ввода.
  • Поскольку фигурные скобки имеют особое значение, мы избегаем их как \{ и \}, чтобы соответствовать фигурным скобкам в начале и конце строки.
  • далее, мы хотим пропустить первые n столбцов - нас это не волнует.
    • Предыдущий столбец - это некоторое количество букв, за которыми следует вертикальная черта, поэтому мы используем стандартный \w для сопоставления со словом-подобным символом (включает цифры и подчеркивание, но почему бы и нет) и * для сопоставления с любым числом из них. Вертикальная черта имеет особое значение, поэтому мы должны экранировать ее как \|. Так как мы хотим сгруппировать это, мы заключаем все это в неотмечающие паренсы (?:\w*\|) (?: делает их не захватывающими). ​​
    • Теперь у нас есть n из предыдущих столбцов, поэтому мы указываем регулярное выражение для сопоставления с шаблоном столбца n раз, используя регулярное выражение count - просто поместите число в фигурные скобки после шаблона. Мы используем стандартную строковую подстановку, поэтому мы просто вводим {#{n}}, что означает «соответствовать предыдущему шаблону ровно n раз.
  • первый столбец без пропусков - тот, о котором мы заботимся, поэтому мы помещаем его в список парней: (\w*)
  • тогда мы пропускаем остальные столбцы, если таковые существуют: (?:\|\w*)*.

Захват столбца переводит его в $1, поэтому мы возвращаем это значение, если регулярное выражение соответствует. Если нет, мы возвращаем ноль, так как эта строка не имеет n-го столбца.

В общем, если вы хотите, чтобы в ваших столбцах было больше, чем просто слова (например, "{a phrase or two|don't forget about punctuation!|maybe some longer strings that have\na newline or two?}"), просто замените все \w в регулярном выражении на [^|{}], чтобы в каждом столбце содержалось что угодно, кроме фигурная скобка или вертикальная черта.


Вот мое предыдущее решение

class String
  def get_column(n)
    raise "not a column string" unless self =~ /\A\{\w*(?:\|\w*)*\}\Z/
    self[1 .. -2].split('|')[n]
  end
end

Мы используем похожее регулярное выражение, чтобы убедиться, что строка содержит набор столбцов или выдает ошибку. Затем мы удаляем фигурные скобки спереди и сзади (используя self[1 .. -2], чтобы ограничить подстроку, начинающуюся с первого символа и заканчивающуюся рядом с последним), разделяем столбцы с помощью символа канала (используя .split('|'), чтобы создать массив столбцов), а затем найдите n-й столбец (используя стандартный поиск Array с [n]).

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

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