preg_split and multiple delimiters

968 views Asked by At

let me start by saying the first number before the first - will be the ID I need to extract. from the first - to the first / will be the 'name' I need to extract. Everything after that I do not care for.

Test String:

1-gc-communications/edit/profile_picture

Expected Output:

Array ( [0] => 1 [1] => gc-communications [2] => /edit/profile_picture )

The best I could come up with was the following patterns (along with their results - with a limit of 3)

Pattern: /-|edit\/profile_picture/
Result: Array ( [0] => 1 [1] => gc [2] => communications/edit/profile_picture )

^ This one is flawed because it does both dashes.

Pattern: /~-~|edit\/profile_picture/
Result: Array ( [0] => 1-gc-communications/ [1] => )

^ major fail.

I know I can do a 2-element limit and just break on the first / and then do a preg_split on the result array, but I would love a way to make this work with one line.

If this is a no-go I am open to other "one liner" solutions.

2

There are 2 answers

1
Andy Ecca On BEST ANSWER

Try this one

$str = '1-gc-communications/edit/profile_picture';
$match = preg_split('#([^-]+)-([^/]+)/(.*)#', $str, 0, PREG_SPLIT_DELIM_CAPTURE);    
print_r($match);

return like as

 array (
    0 => '',
    1 => '1',
    2 => 'gc-communications',
    3 => 'edit/profile_picture',
    4 => '',
  )
0
mickmackusa On

the first number before the first - will be the ID I need to extract. from the first - to the first / will be the 'name' I need to extract. Everything after that I do not care for.

This task seems a great candidate for sscanf() -- it is specifically designed for parsing (scanning) a formatted string. Not only is the syntax brief, you know that you do not need to make repeated matches with the pattern. The output, in case it matters, can be pre-cast as an integer or string for convenience. The remaining string from the first occurring slash are simply ignored.

Code: (Demo)

$str = '1-gc-communications/edit/profile_picture';

var_export(
    sscanf($str, '%d-%[^/]')
    #             ^^ ^^^^^- greedily match one or more non-slash characters
    #             ^^------- greedily match one or more numeric characters   
);

Output:

array (
  0 => 1,                        #<-- integer-typed
  1 => 'gc-communications',      #<-- string-typed
)