В чем разница между этими двумя регулярными выражениями для отслеживания внутренних ссылок на странице?

#ruby #regex

#рубиновый #регулярное выражение

Вопрос:

Я хотел бы иметь возможность сопоставлять якорную часть внутренней ссылки на странице, т.е.:

 "#Welcome"
"#aboutus"
"#services"
"#contactus"
 

Поэтому, чтобы сделать это, я попробовал оба этих регулярных выражения:

  1. /#w*W*/ http://www.rubular.com/r/I3G9X7zkvS
  2. /#(w*)(W*)/ http://www.rubular.com/r/b4Eaar1Tn7

Но если вы посетите каждую из этих страниц, вы заметите, что по какой-то причине обе пропускают 2-ю тестовую строку, что я нахожу странным.

Итак, мой вопрос состоит из трех частей:

  1. Есть ли разница между этими двумя понятиями? Если да, то в чем разница?
  2. Почему ни один из них не улавливает 2-ю строку в моем тестовом образце из этих ссылок?
  3. Существуют ли какие-либо другие правила, которые могут мне понадобиться для правильного захвата любой внутренней ссылки документа? Разрешено ли внутренним ссылкам включать символы и другие странные символы, которые эти регулярные выражения не фиксируют?

Ответ №1:

TL;DR W* является жадным и соответствует символу новой строки, в результате чего регулярное выражение переносится по строкам и совпадает с # в начале следующей строки. Это прерывает второе потенциальное совпадение.

Вы можете исправить это, заменив W* в своем регулярном выражении на [^wn]* , как в этом регулярном выражении:

 /#(w*)([^wn]*)/
 

ДЕМОНСТРАЦИЯ

Ваши вопросы:

  1. Есть ли разница между этими двумя понятиями? Если да, то в чем разница?

Единственное отличие заключается в том, что второе регулярное выражение использует группы захвата. В остальном они одинаковы.

  1. Почему ни один из них не улавливает 2-ю строку в моем тестовом образце из этих ссылок?

W* соответствует любым символам, не являющимся словом, то есть [^a-zA-Z0-9_] . Это означает, что он соответствует символу новой строки n и символу # в начале следующей строки. Другими словами, он «переносит» и не позволяет регулярному выражению соответствовать второй строке. Посмотрите эти демонстрации для ваших регулярных выражений: /#w*W*/ и /#(w*)(W*)/ .

  1. Существуют ли какие-либо другие правила, которые могут мне понадобиться для правильного захвата любой внутренней ссылки документа? Разрешено ли внутренним ссылкам включать символы и другие странные символы, которые эти регулярные выражения не фиксируют?

ДА. Хотя 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"] . Читатели, (?<=#) это позитивный взгляд сзади .