Regex для соответствия хэштегам в предложении с помощью ruby
Я пытаюсь извлечь хэштеги для простого проекта колледжа, используя ruby on rails. Я столкнулся с проблемой с тегами, которые включают только цифры и теги без пространства.
text = "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
регулярное выражение у меня есть /(?:^|s)#(w+)/i
(источник)
это регулярное выражение возвращает #["box", "5", "2good", "first"]
как убедиться, что он возвращает только #["box", "2good"]
и игнорировать остальные, поскольку они не являются "реальным" хэштеги?
3 ответов
можете ли вы попробовать это регулярное выражение:
/(?:^|\s)(?:(?:#\d+?)|(#\w+?))\s/i
обновление 1:
Есть несколько случаев, когда вышеуказанное регулярное выражение не будет соответствовать: #blah23blah и #23blah23.
Следовательно, изменено регулярное выражение, чтобы позаботиться обо всех случаях.
регулярное выражение:
/(?:\s|^)(?:#(?!\d+(?:\s|$)))(\w+)(?=\s|$)/i
поломки:
-
(?:\s|^)
--соответствует предыдущему пробелу или началу строки. Не захватите матч. -
#
--совпадает хэш но не захватывает. -
(?!\d+(?:\s|$)))
--отрицательный Lookahead, чтобы избежать всех числовых символов между # и пробелом (или концом строки) -
(\w+)
--соответствует и захватывает все символы слова -
(?=\s|$)
--положительный Lookahead для обеспечения следующих космоса или конца линия. Это необходимо, чтобы убедиться, что он соответствует соседним допустимым хэш-тегам.
образец текста изменен, чтобы захватить большинство случаев:
#бла Пак мой # коробка с #5 дюжиной #good2 # 3good ликер.#кувшины link.com/liquor#jugs #mkvef214asdwq sd #3e4 flsd #2good #первый#второй #3
матчи:
матч 1: мля
Матч 2: Поле
Матч 3: good2
Матч 4: 3good
Матч 5: mkvef214asdwq
Матч 6: 3e4
Матч 7: сайту 2good
обновление 2:
исключить слова начиная или заканчивая подчеркиванием, просто включите свои исключения в отрицательный lookahead следующим образом:
/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/i
образца, regex и матчи записываются в этот Rubular link
Я бы об этом так:
text.scan(/ #[[:digit:]]?[[:alpha:]]+ /).map{ |s| s.strip[1..-1] }
возвращает:
[
[0] "box",
[1] "2good"
]
Я не пытаюсь делать все в регулярном выражении. Я предпочитаю держать их как можно проще, а затем фильтровать и калечить, как только я получу основные данные. Мое рассуждение заключается в том, что регулярное выражение тем сложнее поддерживать, чем сложнее оно становится. Я бы предпочел потратить свое время на что-то другое, чем поддерживать шаблоны.
попробуйте это:
/\s#([[\d]]?[[a-z]]+\s)/i
выход:
1.9.3-p194 :010 > text = "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
=> "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
1.9.3-p194 :011 > puts text.scan /\s#([[\d]]?[[a-z]]+\s)/i
box
2good
=> nil