1

I have a Slug aktuell/blog/cat1/cat2/cat3 and need a Regex to extract all category-segments (all segements after 'aktuell/blog') from this Slug. The count of cataegory-segements may vary from zero to infinity.

I have already tried several ways but it never works as expected... My last attempt was:

^aktuell\\/blog(?:\\/(\w+))*$/g

But this Regex returns just the last segment as match... What can i do to get all categories?

Thank's

Biruk Abebe
  • 2,235
  • 1
  • 13
  • 24
Nio
  • 497
  • 3
  • 6
  • 16
  • Are you passing the segments into PHP as `$_GET` variables or is the URL only available as a string? If you're passing as variables, cycle through `$_GET` to retrieve the values. If not, then explode the string you have with the delimiter "/" and find the segments you want! – Hugo Pakula May 23 '16 at 07:14
  • The URL is only available as string. I have a routing class which deals with the regex patterns (from db) and returns me the route id and all matches. So I can not use explode... :( – Nio May 23 '16 at 07:17
  • Why not use this pattern: `aktuell\/blog\/(.*)` and explode on `"/"`? – Andreas May 23 '16 at 07:31
  • Pure regex: `/(?:^aktuell\/blog|\G(?!^))(?:\/(\w+))/g` – Sebastian Proske May 23 '16 at 07:39
  • @SebastianProske: I think **you** should post an answer. – Wiktor Stribiżew May 27 '16 at 11:58
  • @WiktorStribiżew thanks for the reminder, but I don't think it's worth the effort to write an answer to this question. – Sebastian Proske May 28 '16 at 08:03

4 Answers4

0

This Regex works, but the php Regex-Engine can't handle matches in a repeating group. Every new match overrides the previous one...

So i have to repeat the group manually:

^aktuell\/blog(?:\/(\w+))?(?:\/(\w+))?(?:\/(\w+))?(?:\/(\w+))?(?:\/(\w+))?
Nio
  • 497
  • 3
  • 6
  • 16
  • Don't you really have access to multiple matches? See Sebastian's suggestion above that would work with `preg_match_all` function (if you remove `g` at the end). – Wiktor Stribiżew May 23 '16 at 07:44
  • Please let him know if his suggestion works, so that he could post an answer to get credit for his suggestion. – Wiktor Stribiżew May 25 '16 at 07:50
0

You can use this piece of code to solve your problem:

$uri = $_SERVER['REQUEST_URI'];
$uri_arr = explode("/",$uri);
$cat = array();
array_map(function($v) use (&$cat){
    preg_match('/^cat\d$/',$v,$matches);
    if(count($matches) > 0){
        $cat[] = $matches[0];
      }
},$uri_arr);
print_r($cat);

Here is an example

Ali
  • 1,408
  • 10
  • 17
0

/(?:^aktuell\/blog|\G(?!^))(?:\/(\w+))/in combination with preg_match_all() works fine!

big thanks to @WiktorStribiżew and @SebastianProske

Nio
  • 497
  • 3
  • 6
  • 16
0

The problem is that repeated captured groups always store the last captured value in their buffer.

You can use a preg_match_all with the following regex:

/(?:^aktuell\/blog|(?!^)\G)\/\K\w+/

or (to avoid escaping the forward slash):

'~(?:^aktuell/blog|(?!^)\G)/\K\w+~'

See the regex demo

Pattern details:

  • (?:^aktuell\/blog|(?!^)\G) - Matches the start of string and aktuell/blog after it (see ^aktuell\/blog), or (|) the end of the previous successful match in the string (with (?!^)\G)
  • \/ - matches a / symbol
  • \K - makes the regex engine omit the text matched so far
  • \w+ - matches /, and then captures 1+ alphanumeric or underscore characters.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563