Вернуть первое совпадение регулярного выражения Ruby


97

Я ищу способ выполнить сопоставление регулярного выражения для строки в Ruby и закоротить его при первом совпадении.

Строка, которую я обрабатываю, длинная и, matchсудя по всему, стандартный способ ( метод) обрабатывает все это целиком, собирает каждое совпадение и возвращает объект MatchData, содержащий все совпадения.

match = string.match(/regex/)[0].to_s

Ответы:


134

Вы могли бы попробовать variableName[/regular expression/]. Это пример вывода irb:

irb(main):003:0> names = "erik kalle johan anders erik kalle johan anders"
=> "erik kalle johan anders erik kalle johan anders"
irb(main):004:0> names[/kalle/]
=> "kalle"

Разве это не совпадение и не возвращение первого результата за кулисами?
Gishu

7
После некоторого тестирования со строками различной длины и просмотра исходного кода C выяснилось, что Regex.match выполняет короткое замыкание и находит только первое совпадение.
Дэниел Бердсли,

3
Аккуратно, не знал об этом ярлыке.
Pierre

Есть ли документация по этому ярлыку? Я искал то, что считал относительно простой задачей, и решил свою проблему только после того, как нашел ее. Спасибо!
dmourati

5
@dmourati Вы можете найти эту функцию, задокументированную в String # [] . Спасибо, что спросили о документе, потому что, читая его, я нашел captureаргумент, который позволяет вам вернуть захват вместо полного совпадения.
slothbear

69

Вы можете использовать []: (что похоже match)

"foo+account2@gmail.com"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"foo+account2@gmail.com"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"

4
лучший полный ответ
akostadinov

23

Если важно только наличие совпадения, вы можете пойти с

/regexp/ =~ "string"

В любом случае matchдолжен возвращать только первое попадание, а scanпоиск выполняется по всей строке. Поэтому если

matchData = "string string".match(/string/)
matchData[0]    # => "string"
matchData[1]    # => nil - it's the first capture group not a second match

8

Я еще не уверен, хороша ли эта функция или просто сумасшедшая, но ваше регулярное выражение может определять локальные переменные.

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"

(Взято с http://ruby-doc.org/core-2.1.1/Regexp.html ).


Отличная особенность! Именно то, что мне было нужно
RaphaMex

Предостережение: это работает только при regex =~ string", not when string = ~ regex`
Кристофер Озбек

2

Регулярное выражение (regex) - это не что иное, как конечный автомат (FSM).

Автомат пытается ответить на вопрос «Возможно ли это состояние или нет?»

Он продолжает попытки найти совпадение с шаблоном до тех пор, пока совпадение не будет найдено (успех), или пока все пути не будут исследованы и совпадение не будет найдено (сбой).

В случае успеха, вопрос «Возможно ли это состояние или нет?» был дан ответ "да". Следовательно, дальнейшее сопоставление не требуется, и регулярное выражение возвращается.

См. This и this, чтобы узнать больше об этом.

Далее: вот интересный пример, демонстрирующий, как работает регулярное выражение. Здесь регулярное выражение используется для определения того, является ли данное число простым. Этот пример написан на Perl, но его также можно написать на Ruby.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.