Соответствие пути URL-адреса, за вычетом расширения имени файла

Какое будет лучшее регулярное выражение для этого сценария?

С учетом этого URL-адреса:

http://php.net/manual/en/function.preg-match.php

Как мне выбрать выбор между (но не включая) http://php.net и .php:

/manual/en/function.preg-match

Это для конфигурационного файла Nginx.

Ответ 1

Вот так:

if (preg_match('/(?<=net).*(?=\.php)/', $subject, $regs)) {
    $result = $regs[0];
}

Пояснение:

"
(?<=      # Assert that the regex below can be matched, with the match ending at this position (positive lookbehind)
   net       # Match the characters "net" literally
)
.         # Match any single character that is not a line break character
   *         # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
(?=       # Assert that the regex below can be matched, starting at this position (positive lookahead)
   \.        # Match the character "." literally
   php       # Match the characters "php" literally
)
"

Ответ 2

Регулярное выражение может быть не самым эффективным инструментом для этого задания.

Попробуйте использовать parse_url() в сочетании с pathinfo():

$url      = 'http://php.net/manual/en/function.preg-match.php';
$path     = parse_url($url, PHP_URL_PATH);
$pathinfo = pathinfo($path);

echo $pathinfo['dirname'], '/', $pathinfo['filename'];

Вышеупомянутый код выводит:

/manual/en/function.preg-match

Ответ 3

Попробуйте следующее:

preg_match("/net(.*)\.php$/","http://php.net/manual/en/function.preg-match.php", $matches);
echo $matches[1];
// prints /manual/en/function.preg-match

Ответ 4

Нет необходимости использовать регулярное выражение для анализа URL-адреса. PHP имеет встроенные функции для этого, pathinfo() и parse_url().

Ответ 5

Просто для удовольствия, вот два способа, которые не были изучены:

substr($url, strpos($s, '/', 8), -4)

Или:

substr($s, strpos($s, '/', 8), -strlen($s) + strrpos($s, '.'))

Основываясь на идее, что схемы HTTP http:// и https:// не более 8 символов, обычно обычно нужно найти первую косую черту с 9-й позиции. Если расширение всегда .php, первый код будет работать, в противном случае требуется другое.

Для чистого решения регулярного выражения вы можете сломать строку так:

~^(?:[^:/?#]+:)?(?://[^/?#]*)?([^?#]*)~
                              ^

Часть пути будет находиться внутри первой группы памяти (то есть индекса 1), обозначенной символом ^ в строке под выражением. Удаление расширения можно выполнить с помощью pathinfo():

$parts = pathinfo($matches[1]);
echo $parts['dirname'] . '/' . $parts['filename'];

Вы также можете настроить выражение следующим образом:

([^?#]*?)(?:\.[^?#]*)?(?:\?|$)

Это выражение не очень оптимально, потому что оно имеет в нем некоторое обратное отслеживание. В конце концов я бы пошел на что-то менее обыденное:

$parts = pathinfo(parse_url($url, PHP_URL_PATH));
echo $parts['dirname'] . '/' . $parts['filename'];

Ответ 6

Это общее совпадение URL-адресов позволяет вам выбирать части URL-адреса:

if (preg_match('/\\b(?P<protocol>https?|ftp):\/\/(?P<domain>[-A-Z0-9.]+)(?P<file>\/[-A-Z0-9+&@#\/%=~_|!:,.;]*)?(?P<parameters>\\?[-A-Z0-9+&@#\/%=~_|!:,.;]*)?/i', $subject, $regs)) {
    $result = $regs['file'];
    //or you can append the $regs['parameters'] too
} else {
    $result = "";
}

Ответ 7

Здесь решение регулярных выражений лучше, чем большинство из них до сих пор, если вы спросите меня: http://regex101.com/r/nQ8rH5

/http:\/\/[^\/]+\K.*(?=\.[^.]+$)/i

Ответ 8

Простой:

$url = "http://php.net/manual/en/function.preg-match.php";
preg_match("/http:\/\/php\.net(.+)\.php/", $url, $matches);
echo $matches[1];

$matches[0] - ваш полный URL, $matches[1] - это часть, которую вы хотите.

Посмотрите сами: http://codepad.viper-7.com/hHmwI2

Ответ 9

| (? & Л; =\ш)/.+ (?. =\\ Ш + $) |

  • выберите все из первого литерала '/', которому предшествует
  • смотреть за символом Word (\ w)
  • до следующего обзора
    • literal '.' добавлено
    • один или несколько символов Word (\ w)
    • до конца $
  re> |(?<=\w)/.+(?=\.\w+$)|
Compile time 0.0011 milliseconds
Memory allocation (code space): 32
  Study time 0.0002 milliseconds
Capturing subpattern count = 0
No options
First char = '/'
No need char
Max lookbehind = 1
Subject length lower bound = 2
No set of starting bytes
data> http://php.net/manual/en/function.preg-match.php
Execute time 0.0007 milliseconds
 0: /manual/en/function.preg-match

|//[^/] *\\ ш + $(. *) |.

  • найдите два литерала '//', за которым следует что-либо, кроме буквального '/'
  • выберите все, пока
  • найти литерал '.' за которым следуют только символы Word\w до конца $
  re> |//[^/]*(.*)\.\w+$|
Compile time 0.0010 milliseconds
Memory allocation (code space): 28
  Study time 0.0002 milliseconds
Capturing subpattern count = 1
No options
First char = '/'
Need char = '.'
Subject length lower bound = 4
No set of starting bytes
data> http://php.net/manual/en/function.preg-match.php
Execute time 0.0005 milliseconds
 0: //php.net/manual/en/function.preg-match.php
 1: /manual/en/function.preg-match

|/[^/] +\(*.) |.

  • найдите литерал '/', за которым следует хотя бы 1 или более нелитературный '/'
  • агрессивный выбор всего до последнего литерала '.
  re> |/[^/]+(.*)\.|
Compile time 0.0008 milliseconds
Memory allocation (code space): 23
  Study time 0.0002 milliseconds
Capturing subpattern count = 1
No options
First char = '/'
Need char = '.'
Subject length lower bound = 3
No set of starting bytes
data> http://php.net/manual/en/function.preg-match.php
Execute time 0.0005 milliseconds
 0: /php.net/manual/en/function.preg-match.
 1: /manual/en/function.preg-match

|/[^/] +\К * (= \?.) |.

  • найдите литерал '/', за которым следует хотя бы 1 или более нелитературный '/'
  • Reset выберите start\K
  • агрессивный выбор всего до
  • Посмотрите вперед последний литерал '.'
  re> |/[^/]+\K.*(?=\.)|
Compile time 0.0009 milliseconds
Memory allocation (code space): 22
  Study time 0.0002 milliseconds
Capturing subpattern count = 0
No options
First char = '/'
No need char
Subject length lower bound = 2
No set of starting bytes
data> http://php.net/manual/en/function.preg-match.php
Execute time 0.0005 milliseconds
 0: /manual/en/function.preg-match

|\ш +\К/.* (= \?.) |

  • найдите один или несколько символов Word (\ w) перед литералом '/'
  • Reset выберите start\K
  • выберите литерал '/', а затем
  • ничего перед
  • Посмотрите вперед последний литерал '.'
  re> |\w+\K/.*(?=\.)|
Compile time 0.0009 milliseconds
Memory allocation (code space): 22
  Study time 0.0003 milliseconds
Capturing subpattern count = 0
No options
No first char
Need char = '/'
Subject length lower bound = 2
Starting byte set: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P 
  Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z 
data> http://php.net/manual/en/function.preg-match.php
Execute time 0.0011 milliseconds
 0: /manual/en/function.preg-match

Ответ 10

Регулярное выражение для сопоставления всего после "net" и перед ".php":

$pattern = "net([a-zA-Z0-9_]*)\.php"; 

В приведенном выше регулярном выражении вы можете найти подходящую группу символов, заключенных в()(), чтобы быть тем, что вы ищете.

Надеюсь, что это полезно.

Ответ 11

http:[\/]{2}.+?[.][^\/]+(.+)[.].+

посмотрим, что он сделал:

http:[\/]{2}.+?[.][^\/] - группа без захвата для http://php.net

(.+)[.] - захватить часть до последней точки: /manual/en/function.preg-match

[.].+ - сопоставление расширения файла следующим образом: .php