简体   繁体   中英

Get all matches in a regular expression

I have this URL:

uploads/offers/picture/_YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS_/_wyMDAiO30=_/518edc82d94b0-201341717250_descuen_a06d000000fkvwpiak_1_1.jpg 

And I need to get all /_(.*)_/ parts, but my preg_match_all expression seems bad formed:

preg_match_all('#/_([^_/]+)_/#', $url, $params);

Returns

Array
(
    [0] => Array
        (
            [0] => /_YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS_/
        )
    [1] => Array
        (
            [0] => YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS
        )
)

And I need

Array
(
    [0] => Array
        (
            [0] => /_YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS_/
            [1] => /_wyMDAiO30=_/
        )
    [1] => Array
        (
            [0] => YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS
            [1] => wyMDAiO30=
        )
)

Some problem with common string parts in expression?

The final / in the regex ends up consuming it. One simple way to get around this is to use a lookahead.

preg_match_all('#/_([^_/]+)_(?=/)#', $url, $params);

The / in between doesn't match twice, however, you could use lookahead/behind assertions:

preg_match_all('#(?<=/_)[^_/]+(?=_/)#', $url,$params);

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(50) "YToxOntzOjc6Im9wdGlvbnMiO3M6MTY6Inpvb21Dcm9wLDI4MS"
    [1]=>
    string(10) "wyMDAiO30="
  }
}

One problem with your current solution is that it matches the / at the end of the expression as Explosion Pill's answer says; using positive lookahead will solve that problem.

Another possible issue is that the [^_/] part may end up breaking the regex if the input contains underscores as part of the matches you do want to capture.

To solve both issues at once:

~/_(.+?)_(?=/)~

This seems to me to be closer to what you are after: "whenever you see the sequence /_ start capturing all input until you come across the sequence _/ ". Lone underscores inside the input will not break this.

Your expression picks up TWO _ , so the wyMDAiO30= part is skipped.

I suggest you use explode("_", $url) (or preg_split(...) if the above is just an example and you need regexes to recognize splitting characters/substrings).

If you really insist on using preg_match_all , check the documentation. There is a way to say "match this, but don't include it in the string". I think it's something like #_([^_/]+)(?=_)# .

Best solution would probably be to split the string first and then check for underscores:

<?php

$data = explode('/', $url);

foreach($data as $val) {
    if(substr($val, 0, 1) === '_' && substr($val, -1) === '_') {
        // ok
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM