2015-12-07 2 views
2

у меня есть это PHP регулярное выражение:Regex группа захвата всегда как первый

https?://(?:[a-z0-9]+\.)?livestream\.com/(?:(accounts/[0-9]+/events/[0-9]+(?:/videos/[0-9]+)?)|[^\s/]+/video\?clipId=([^\s&]+)|([^\s/]+))

мне нравится, чтобы соответствовать следующим URL-адресов с результатами.

http://original.livestream.com/bethanychurchnh = bethanychurchnh 

http://original.livestream.com/bethanychurchnh/video?clipId=flv_b54a694b-043c-4886-9f35-03c8008c23 = flv_b54a694b-043c-4886-9f35-03c8008c23 

http://livestream.com/accounts/142499/events/3959775 = accounts/142499/events/3959775 

http://livestream.com/accounts/142499/events/3959775/videos/83958146 = /accounts/142499/events/3959775/videos/83958146 

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

ответ

2

Вы можете использовать сброс ветви в своем регулярном выражении:

https?:\/\/(?:[a-z0-9]+\.)?livestream\.com\/(?|(accounts\/[0-9]+\/events\/[0-9]+(?:\/videos\/[0-9]+)?)|[^\s\/]+\/video\?clipId=([^\s&]+)|([^\s\/]+)) 
              ^^ 

См regex demo

смотри описание branch reset at regular-expressions.info:

Alternatives внутри доли филиал группы сброса те же захватывая группы. Синтаксис равен (?|regex), где (?| открывает группу, а регулярное выражение - любое регулярное выражение. Если вы не используете какие-либо группы чередования или захвата внутри группы сброса ветвей, то ее специальная функция не вступает в игру. Затем он действует как non-capturing group.

1

Другая возможность, вы можете позволить дублировать названные захваты с (?J)

$pattern = '~(?J)https?://(?:[a-z0-9]+\.)?livestream\.com/ 
(?: 
    (?<id>accounts/[0-9]+/events/[0-9]+(?:/videos/[0-9]+)?) 
    | 
    [^\s/]+/video\?clipId=(?<id>[^\s&]+) 
    | 
    (?<id>[^\s/]+) 
)~x'; 

if (preg_match($pattern, $text, $m)) 
    echo $m['id']; 

demo

или с тех пор, что вы ищете всегда в конце шаблона, вам не нужно группа захвата вообще с функцией \K, которая удаляет все слева от всего результата матча:

$pattern = '~https?://(?:[a-z0-9]+\.)?livestream\.com/ \K 
(?: 
    accounts/[0-9]+/events/[0-9]+(?:/videos/[0-9]+)? 
    | 
    [^\s/]+(?:/video\?clipId=\K[^\s&]+)? 
)~x'; 

if (preg_match($pattern, $text, $m)) 
    echo $m[0]; 
Смежные вопросы