Лучше использовать группы наблюдения или захвата? - PullRequest
4 голосов
/ 25 января 2010

Я не уверен, что один из них «лучше», чем другой, и почему это так, но у меня есть оригинальная строка, которая выглядит следующим образом:

$string = '/random_length_user/file.php';

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

preg_match("%(?<=^/)([^/]*)%", $string, $capture);
preg_match("%^/([^/]*)%", $string, $capture);

Они возвращаются в порядке:

Array
(
    [0] => random_length_user
)
Array
(
    [0] => /random_length_user
    [1] => random_length_user
)

По сути, я получаю желаемый результат в $ capture [0], используя просмотр в обратном направлении, и в $ capture [1] без. Теперь вопрос в том ... есть ли причина предпочитать один из этих методов другому?

Ответы [ 2 ]

3 голосов
/ 25 января 2010

Вероятно, это не имеет значения с preg_match, но это будет иметь значение при использовании preg_replace, поскольку оно влияет на то, что будет заменено.

Это также может быть проблемой при глобальном сопоставлении, поскольку группа захвата будет потреблять символы, в то время как обходные пути не будут

Тривиальный пример:

  • /(?<=a)a/g с 'aaaa' дает Array('a', 'a', 'a')
  • /(a)a/g с 'aaaa' дает Array('aa', 'aa')
1 голос
/ 26 января 2010

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

preg_match("%^/\w+/([^/]*)%", '/random_length_user/file.php');

Array
(
    [0] => /random_length_user/file.php
    [1] => file.php
)

... но подход lookbehind - нет, потому что выражения lookbehind могут соответствовать только фиксированному количеству символов. Однако есть еще лучшая альтернатива: \K, оператор MATCH POINT RESET. Куда бы вы ни указали, механизм регулярных выражений делает вид, что матч действительно начался там. Таким образом, вы получите тот же результат, что и при просмотре сзади, без ограничения фиксированной длины:

preg_match('%^/\w+/\K[^/]+$%', '/random_length_user/file.php');

Array
(
    [0] => file.php
)

Насколько я знаю, эта функция доступна только в Perl 5.10+ и в инструментах (например, в PHP preg_ функциях), которые работают с библиотекой PCRE. Для справки PCRE см. справочную страницу и поиск (F3) для \K.

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