#ruby #regex
#рубиновый #регулярное выражение
Вопрос:
Я хотел бы иметь возможность сопоставлять якорную часть внутренней ссылки на странице, т.е.:
"#Welcome"
"#aboutus"
"#services"
"#contactus"
Поэтому, чтобы сделать это, я попробовал оба этих регулярных выражения:
/#w*W*/
— http://www.rubular.com/r/I3G9X7zkvS/#(w*)(W*)/
— http://www.rubular.com/r/b4Eaar1Tn7
Но если вы посетите каждую из этих страниц, вы заметите, что по какой-то причине обе пропускают 2-ю тестовую строку, что я нахожу странным.
Итак, мой вопрос состоит из трех частей:
- Есть ли разница между этими двумя понятиями? Если да, то в чем разница?
- Почему ни один из них не улавливает 2-ю строку в моем тестовом образце из этих ссылок?
- Существуют ли какие-либо другие правила, которые могут мне понадобиться для правильного захвата любой внутренней ссылки документа? Разрешено ли внутренним ссылкам включать символы и другие странные символы, которые эти регулярные выражения не фиксируют?
Ответ №1:
TL;DR W*
является жадным и соответствует символу новой строки, в результате чего регулярное выражение переносится по строкам и совпадает с #
в начале следующей строки. Это прерывает второе потенциальное совпадение.
Вы можете исправить это, заменив W*
в своем регулярном выражении на [^wn]*
, как в этом регулярном выражении:
/#(w*)([^wn]*)/
Ваши вопросы:
- Есть ли разница между этими двумя понятиями? Если да, то в чем разница?
Единственное отличие заключается в том, что второе регулярное выражение использует группы захвата. В остальном они одинаковы.
- Почему ни один из них не улавливает 2-ю строку в моем тестовом образце из этих ссылок?
W*
соответствует любым символам, не являющимся словом, то есть [^a-zA-Z0-9_]
. Это означает, что он соответствует символу новой строки n
и символу #
в начале следующей строки. Другими словами, он «переносит» и не позволяет регулярному выражению соответствовать второй строке. Посмотрите эти демонстрации для ваших регулярных выражений: /#w*W*/
и /#(w*)(W*)/
.
- Существуют ли какие-либо другие правила, которые могут мне понадобиться для правильного захвата любой внутренней ссылки документа? Разрешено ли внутренним ссылкам включать символы и другие странные символы, которые эти регулярные выражения не фиксируют?
ДА. Хотя hash ( #
) — единственный способ указать внутреннюю ссылку (a / k / a anchor link или hash link), существует множество способов создания ссылки. То есть его может не быть в самом HTML. Здесь есть много возможностей, таких как полный URL ( http://example.com/foo/bar#baz
), ссылки JavaScript и многие другие особенности. И, конечно, у вас может быть текст, соответствующий вашему регулярному выражению ( #2 pencil
), который не является ссылкой. Но попытка обсудить все эти проблемы сделала бы этот ответ слишком длинным (и сделала бы ваш вопрос слишком широким).
Комментарии:
1. Интересно. Итак, причина, по которой 2-й вариант не сопоставляется в моих ссылках, заключается в переносе из
W
? Итак, чтобы захватить все буквы, цифры и, возможно, дефисы в якорной ссылке, что я должен использовать вместоW
?2. @marcamillion Правильно. Вы могли бы избежать этого, заменив
W*
на[^wn]*
. Посмотрите эту демонстрацию .3. Вы могли бы использовать `/ # w * [^#] */.
4. @CarySwoveland Верно, хотя я подозреваю, что OP также предпочел бы не включать
n
как часть ссылки.5. Эд, да. Возможно
str.scan /(?<=#)w / #=> ["aboutus", "contact", "welcome"]
, илиstr.scan(/#(w )/).flatten #=> ["aboutus", "contact", "welcome"]
. Читатели,(?<=#)
это позитивный взгляд сзади .