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

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

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

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

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

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

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

Ответ 1

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

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

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

Ответ 2

@Rob: Я не согласен. Чтобы обеспечить соблюдение того, о чем вы просите, я думаю, вам нужно использовать отрицательный внешний вид, что возможно, но, конечно же, не связано с использованием {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 >

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

Ответ 3

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

Ответ 4

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

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

Вы должны прочитать это как: "захватить материал в parens ровно один раз". Но мы не заботимся об этом, чтобы использовать его позже, например, $1 взамен. Так что это бессмысленно.