Как работает этот негативный взгляд?

Этот фрагмент кода взят из книги "Освоение регулярных выражений". У меня возникают проблемы с пониманием последней части с негативным взглядом (комментарий # Not allowed to end with [.,?!]). Как это выражение упадет [?!,.] от http://www.google.com/foo! или же http://www.google.com/bar\!?

# Turn HTTP URLs into links . . . 
$text =~ s{
   \b
   # Capture the URL to $1 . . . 
   (
      http:// [-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info) \b   # hostname
      (
         / [-a-z0-9_:\@&?=+,.!/~*'%\$]* # Optional path
         (?<![.,?!])    # Path not allowed to end with [.,?!]
      )?
   )
}{<a href="$1">$1</a>}gix;

print $text; # Finally, display the HTML-ized text.

2 ответа

Я не буду. Он находится в той части выражения, в которой сопоставляется необязательный путь, и поскольку в http://www.google.com, это не будет иметь никакого эффекта.

Идея в том, когда [-a-z0-9_:@&?=+,.!/~*%\$]+ поглотил все, что может, он передает контроль назад. Если наблюдатель видит один из этих знаков препинания предложения, он сообщает об ошибке и передает управление обратно [-a-z0-9_:\@&?=+,.!/~*%\$]+ часть. Он отступает на одну позицию, "возвращая" последний использованный символ, а затем снова отдает взгляд назад.

В случае www.google.com/foo!Смотритель теперь будет смотреть на o, так что он сообщает об успехе, и общий матч проходит успешно.

Тем не менее, когда вы пытаетесь сопоставить www.google.com/bar\! Смотритель никогда не получает возможность взглянуть на челку (!). [-a-z0-9_:\@&?=+,.!/~*%\$]+ не соответствует обратным слешам, потому что они недопустимы в URL. Останавливается после употребления r, и на этот раз взгляд назад успешно, без необходимости отступать.

РЕДАКТИРОВАТЬ: В ответ на вопрос в комментариях: да, вы можете использовать что-то вроде этого:

\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|$!:,.;]*[A-Z0-9+&@#/%=~_|$]

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

Другие вопросы по тегам