Вернуть первое совпадение регулярного выражения 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"
Presidenten
источник
Разве это не совпадение и не возвращение первого результата за кулисами?
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
Slartibartfast
источник
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.

Лакмус
источник