Назначение {1} в этом регулярном выражении для сопоставления протоколов URL - PullRequest
4 голосов
/ 17 августа 2008

Я читал этот вопрос о том, как анализировать URL-адреса с веб-страниц, и у меня был вопрос о принятом ответе , который предлагал это решение:

((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)

Решение было предложено csmba , и он зачислил его на regexlib.com . Уф. Кредиты сделаны.

Я думаю, что это довольно наивное регулярное выражение, но это хорошая отправная точка для создания чего-то лучшего. Но мой вопрос таков:

Какой смысл {1}? Это означает "точно одна из предыдущих группировок", верно? Разве это не стандартное поведение группировки в регулярном выражении? Изменится ли выражение каким-либо образом, если удалить {1}?

Если бы я увидел это от коллеги, я бы указал на его или ее ошибку, но когда я пишу это, ответ оценивается в 6, а выражение на regexlib.com оценивается в 4 из 5. Так что, возможно, я пропускаю что-то?

Ответы [ 4 ]

3 голосов
/ 17 августа 2008

@ Роб : Я не согласен. Чтобы выполнить то, о чем вы просите, я думаю, что вам нужно использовать отрицательный взгляд, что возможно, но, безусловно, не связано с использованием {1}. Ни одна из версий регулярного выражения не решает эту конкретную проблему.

Чтобы код говорил:

tibook 0 /home/jj33/swap > cat text
Text this is http://example.com text this is
Text this is http://http://example.com text this is
tibook 0 /home/jj33/swap > cat p
#!/usr/bin/perl

my $re1 = '((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)';
my $re2 = '((mailto\:|(news|(ht|f)tp(s?))\://)\S+)';

while (<>) {
  print "Evaluating: $_";
  print "re1 saw \$1 = $1\n" if (/$re1/);
  print "re2 saw \$1 = $1\n" if (/$re2/);
}
tibook 0 /home/jj33/swap > cat text | perl p
Evaluating: Text this is http://example.com text this is
re1 saw $1 = http://example.com
re2 saw $1 = http://example.com
Evaluating: Text this is http://http://example.com text this is
re1 saw $1 = http://http://example.com
re2 saw $1 = http://http://example.com
tibook 0 /home/jj33/swap >

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

2 голосов
/ 17 августа 2008

Я не думаю, что {1} имеет какую-либо допустимую функцию в этом регулярном выражении.

(** почты: |? (Новости | (ХТ | е) ф (s)): // ) {1} **

Вы должны прочитать это как: «Захватите вещи в паренсе ровно один раз». Но на самом деле нам не важно захватить это для последующего использования, например, 1 доллар на замену. Так что это бессмысленно.

1 голос
/ 17 августа 2008

@ Джефф Этвуд, ваша интерпретация немного ошибочна - означает, что {1} означает совпадение ровно один раз, но не влияет на «захват» - захват происходит из-за скобок - фигурные скобки указывают только количество раз шаблон должен соответствовать источнику - один раз, как вы говорите.

Я согласен с @Marius, даже если его ответ немного лаконичен и может показаться легкомысленным. Регулярные выражения сложны, если их не привыкли, а {1} в вопросе не совсем ошибка - в системах, которые его поддерживают, это означает «ровно одно совпадение». В этом смысле он ничего не делает.

К сожалению, в отличие от удаленного сообщения, регулярное выражение не удерживает совпадение http://http://example.org, так как \ S + в конце будет соответствовать одному или нескольким непробельным символам, включая http://example.org в http://http://example.org (проверено с использованием Python 2.5, на случай, если мое чтение регулярных выражений было отключено). Таким образом, данное регулярное выражение на самом деле не самое лучшее. Я не эксперт по URL, но, вероятно, что-то, ограничивающее появление ":" s и "//" после первого, будет необходимо (но вряд ли достаточно) для обеспечения хороших URL.

1 голос
/ 17 августа 2008

Я не думаю, что это имеет какое-либо назначение. Но поскольку RegEx практически невозможно понять / разложить, люди редко указывают на ошибки. Вероятно, поэтому никто не указал на это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...