Поверніть перший матч регексу 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
Після деякого тестування з різними рядками довжини і перегляду джерела С, виявляється, Regex.match робить коротке замикання і знаходить лише першу відповідність.
Даніель Бердслі

3
Акуратний, не знав про цю ярлику.
П'єр

Чи є якась документація на цей ярлик? Я шукав високо і низько те, що, на мою думку, було відносно простим завданням, і вирішив своє питання лише після того, як знайшов це. Дякую!
dmourati

5
@dmourati Ця функція може бути задокументована у рядку № [] . Дякуємо, що запитали про doc, оскільки, прочитавши його, я знайшов captureаргумент - який дозволяє повернути знімок замість повного збігу.
lethbear

68

Ви можете використовувати []: (що схоже 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

Caveat: працює лише тоді, коли regex =~ string", not when string = ~ regex`
Крістофер Оезбек

2

Регулярне вираження (регулярний вираз) - це не що інше, як машина кінцевого стану (FSM).

FSM намагається відповісти на питання "Чи можливий цей стан чи ні?"

Він продовжує намагатися встановити збіг шаблонів, поки не буде знайдено збіг (успіх) або поки не будуть досліджені всі шляхи та не знайдено відповідності (невдача).

На успіх питання "Чи можливий такий стан чи ні?" відповіли "так". Отже, подальше узгодження не потрібно, і регулярний вираз повертається.

Дивіться це та це для більш детального на цьому.

Далі: ось цікавий приклад продемонструвати, як працює гегекс. Тут використовується регулярний вираз, щоб визначити, чи є дане число простим. Цей приклад є в perl, але він також може бути написаний у рубіні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.