Выделения в регулярных выражениях

Позиционные выделения
Именованные выделения
Сохранение позиционного выделения

Регулярные выражения, используемые в директивах location, server_name, if, map и ряде других, могут содержать выделения. На выделенную подстроку можно сослаться либо по номеру, как “$1”...“$9”, либо по имени. Эти две формы отличаются тем, как долго выделенное значение остаётся доступным.

Всё описанное ниже относится также к директивам server_name и map модуля stream.

Позиционные выделения

Позиционные выделения нумеруются в порядке следования выделяющих скобок в регулярном выражении:

location ~ ^/images/(.*)\.([a-z]+)$ {
    # для запроса "/images/cats/tom.jpg"
    # $1 равно "cats/tom", а $2 равно "jpg"
}

Позиционные выделения не являются переменными. Они образуют единый набор значений, общий для всех этих директив в процессе обработки запроса или соединения. Успешное сопоставление заменяет весь набор целиком, а неуспешное может его очистить. Поэтому значения доступны только до следующего сопоставления, которое может произойти в никак не связанной директиве.

Сопоставление может произойти и неявно. Поскольку переменные вычисляются только в момент использования, обращение к переменной map, в исходных значениях которой заданы регулярные выражения, приводит к сопоставлению с ними в этот момент, и успешное сопоставление заменяет позиционные выделения:

map $uri $mapped {
    ~^/(?<first>[^/]+)/  $first;
}

location ~ ^/images/(.*)$ {
    set $name   $1;   # "cats/tom.jpg"
    set $m      $mapped;     # "images"
    set $name2  $1;   # "images", а не "cats/tom.jpg"
}

Именованные выделения

Выделению можно дать имя:

location ~ ^/images/(?<name>.*)\.(?<ext>[a-z]+)$ {
    ...
}

Именованные выделения создают обычные переменные nginx, в данном случае $name и $ext. Их значения не заменяются при сопоставлении других регулярных выражений, если только в них не используется то же имя выделения. Поэтому именованные выделения предпочтительнее, если выделенное значение нужно передать в директиву, отличную от той, в которой было выполнено сопоставление.

Библиотека PCRE поддерживает именованные выделения, используя следующий синтаксис:

?<name> Совместимый с Perl синтаксис
?'name' Совместимый с Perl синтаксис
?P<name> Python-совместимый синтаксис

Сохранение позиционного выделения

Если позиционное выделение нужно использовать позднее и его нельзя заменить именованным, значение следует скопировать в переменную сразу после сопоставления с помощью директивы set (set в модуле stream):

location ~ ^/images/(.*)$ {
    set $name $1;
}