3

How do I split a string by , but skip the one that's inside an array

String - "'==', ['abc', 'xyz'], 1"

When I do explode(',', $expression) it's giving me 4 item in array

array:4 [
   0 => "'=='"
   1 => "['abc'"
   2 => "'xyz']"
   3 => 1
]

But I want my output to be -

array:3 [
   0 => "'=='"
   1 => "['abc', 'xyz']"
   2 => 1
]
Michael Shopsin
  • 2,055
  • 2
  • 24
  • 43
Amitoz Deol
  • 442
  • 5
  • 16
  • 1
    You might be looking for something like this http://php.net/manual/fr/function.preg-split.php – Gregoire Ducharme Jun 12 '18 at 15:39
  • 1
    How have you ended up with a string in this format? It feels like this might be solved more easily earlier in the process. – iainn Jun 12 '18 at 15:43
  • 2
    Possible duplicate of [PHP: split string on comma, but NOT when between braces or quotes?](https://stackoverflow.com/questions/15233953/php-split-string-on-comma-but-not-when-between-braces-or-quotes) – iainn Jun 12 '18 at 15:44
  • In laravel 5.6, Im getting this error message when I'm creating a custom Blade directive `Blade::directive('role', function($symbol, $check_roles){ ..... }` Error: `Type error: Too few arguments to function App\Providers\RoleServiceProvider::App\Providers\{closure}(), 1 passed and exactly 2 expected` Inside my view : `@role('==', ['Manager', 'User'])`. Turns out laravel convert all the arguments into a string. So now i have to parse it like so. – Amitoz Deol Jun 12 '18 at 15:45
  • 3
    @AmitozDeol If this is to work around a limitation with custom Blade directives only supporting one argument, I'd *strongly* recommend passing both arguments as either an array, object, or JSON-encoded string. Trying to split apart a string of multiple arguments apart is solving the wrong problem. – iainn Jun 12 '18 at 15:54

3 Answers3

6

yeah, regex - select all commas, ignore in square brakets

/[,]+(?![^\[]*\])/g

https://regexr.com/3qudi

offwhite
  • 552
  • 1
  • 4
  • 9
  • The comma doesn't benefit from being inside of a character class. The `g` pattern modifier is not needed in php. – mickmackusa Mar 26 '21 at 03:06
1

For your example data you might use preg_split and use a regex to match a comma or match the part with the square brackets and then skip that using (*SKIP)(*FAIL).

,|\[[^]]+\](*SKIP)(*FAIL)

$pattern = '/,|\[[^]]+\](*SKIP)(*FAIL)/';
$string = "'==', ['abc', 'xyz'], 1";
$result = preg_split($pattern, $string);
print_r($result);

That would give you:

Array
(
    [0] => '=='
    [1] =>  ['abc', 'xyz']
    [2] =>  1
)

Demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
0

For your example, if you don't want to use regex and want to stick with the explode() function you are already using, you could simply replace all instances of ', ' with ',', then break the string in parts by , (followed by a space) instead of just the comma.

This makes it so things inside the brackets don't have the explode delimiter, thus making them not break apart into the array.

This has an additional problem, if you had a string like '==', 'test-taco', this solution would not work. This problem, along with many other problems probably, can be solved by removing the single quotes from the separate strings, as ==, test-taco would still work.

This solution should work if your strings inside brackets are valid PHP arrays/JSON string

$str = "'==', ['abc', 'xyz'], 1";
$str = str_replace("', '", "','", $str);
$str = explode(", ", $str);

Though I recommend regex as it may solve some underlying issues that I don't see.

Output is:

Array
(
    [0] => '=='
    [1] => ['abc','xyz']
    [2] => 1
)
GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71