2

I have the following data which is displaying as this

{123456  123456  123456}
{654321  654321  654321}
{123456  123456  123456}

My PHP Code:

$myarray = preg_split("/(\s|{\s)/", $data);
print_r($myarray);

The output of my array is like this:

[0] => {123456
[1] => 123456
[2] => 123456}
[3] => {654321
[4] => 654321
[5] => 654321}
[6] => {123456
[7] => 123456
[8] => 123456}

My question is, how to hide [0], [3] and [6] from the output? if you noticed, they start with a { I'm not sure if I did a mistake coding the preg_split function

Desired behavior:

if the data is like this

{1  2  3}
{4  5  6}
{7  8  9}

the desired output should be like this:

[0] => 2
[1] => 3
[2] => 5
[3] => 6
[4] => 8
[5] => 9
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
thebest man
  • 109
  • 5
  • why not remove the curly braces before the regex using `str_replace` or similar? – Professor Abronsius Sep 30 '21 at 21:55
  • because the curly braces are generated along with the data itself, do you have any idea how to get rid of it, however even if you can do it, i still don't need that data in array[0],[1] and [3] to be displayed at all – thebest man Sep 30 '21 at 22:16
  • what criteria is there to either hiding or displaying the resultant numbers? There are duplicates in the data - that presumably is fine? – Professor Abronsius Sep 30 '21 at 22:18
  • array[0] must be hidden, array[1] must be visible, array [2] must be visible then array[3] must be hidden, the numbers are only for making examples, i can't share real data – thebest man Sep 30 '21 at 22:23
  • Why are you using `preg_split()` instead of `preg_match_all()` to get the numbers? – Barmar Sep 30 '21 at 22:25

4 Answers4

0

Change {\s to {\d+\s so that {123456 will be a delimiter and not be included in the result.

You don't need the capture group around the regular expression.

$data = '{123456  123456  123456}
{654321  654321  654321}
{123456  123456  123456}';
$myarray = preg_split("/\s|{\d+\s/", $data);
print_r($myarray);

Output:

Array
(
    [0] => 
    [1] => 
    [2] => 123456
    [3] => 
    [4] => 123456}
    [5] => 
    [6] => 
    [7] => 654321
    [8] => 
    [9] => 654321}
    [10] => 
    [11] => 
    [12] => 123456
    [13] => 
    [14] => 123456}
)

If you also don't want } in the results, that needs to be in the regexp as well.

$myarray = preg_split("/\s+|\s*\{\d+\s*|\s*\}\s*/", $data);

You could also use a regular expression that matches a number unless it's preceded by {, using a negative lookbehind.

$data = '{1 2 3} {4 5 6} {7 8 9}';
preg_match_all('/(?<!{)\d+/', $data, $match);
$myarray = $match[0];
print_r($myarray);

Output:

Array
(
    [0] => 2
    [1] => 3
    [2] => 5
    [3] => 6
    [4] => 8
    [5] => 9
)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thank you @Barmar for your input, if the data is like this ` {1 2 3} {4 5 6} {7 8 9}` the desired output should be like this: `[0] => 2 [1] => 3 [2] => 5 [3] => 6 [4] => 8 [5] => 9` please check my question edit – thebest man Sep 30 '21 at 23:28
  • You can remove the empty elements with `array_filter()`. – Barmar Sep 30 '21 at 23:29
  • I don't know why the solution provided didn't work out for my production code. but it does work if I hardcode the data in the array as you did. – thebest man Sep 30 '21 at 23:32
  • Your original question didn't say anything about removing the `}` at the end of elements 2, 5, and 8. But your edit doesn't have them. – Barmar Sep 30 '21 at 23:33
  • I get `[0] => [1] => 2 [2] => 3} [3] => [4] => 5 [5] => 6} [6] => [7] => 8 [8] => 9}` – Barmar Sep 30 '21 at 23:33
  • I've updated the answer. – Barmar Sep 30 '21 at 23:39
0

Not everything needs a regular expression.

$input = <<<_E_
{123456  123456  123456}
{654321  654321  654321}
{123456  123456  123456}
_E_;

$lines = explode("\n", $input);
$lines = array_map(function($a){return trim($a, '{}');}, $lines);
$lines = array_map(function($a){return explode(' ', $a);}, $lines);
$lines = array_map('array_filter', $lines);
$items = array_merge(...$lines);

var_dump($lines, $items);

Output:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(6) "123456"
    [2]=>
    string(6) "123456"
    [4]=>
    string(6) "123456"
  }
  [1]=>
  array(3) {
    [0]=>
    string(6) "654321"
    [2]=>
    string(6) "654321"
    [4]=>
    string(6) "654321"
  }
  [2]=>
  array(3) {
    [0]=>
    string(6) "123456"
    [2]=>
    string(6) "123456"
    [4]=>
    string(6) "123456"
  }
}
array(9) {
  [0]=>
  string(6) "123456"
  [1]=>
  string(6) "123456"
  [2]=>
  string(6) "123456"
  [3]=>
  string(6) "654321"
  [4]=>
  string(6) "654321"
  [5]=>
  string(6) "654321"
  [6]=>
  string(6) "123456"
  [7]=>
  string(6) "123456"
  [8]=>
  string(6) "123456"
}
Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • This doesn't seem right. There should only be 2 matches per row, not 3. It shouldn't include the first number after `{`. – Barmar Sep 30 '21 at 23:30
0

Not everything needs a regular expression, but sometimes it is the most direct tool for the job.

Split the string on all characters that you don't want to keep.

Code: (Demo)

var_export(
    preg_split(
        '/ +|}\R?|{\d+/',
        $text,
        0,
        PREG_SPLIT_NO_EMPTY
    )
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

Not sure if preg_split() is required, but you could do this with a match all and then gather what's found:

$foo = trim('
{555555  123456  123456}
{666666  654321  654321}
{777777  123456  123456}
');

$items = [];

if (preg_match_all('/^{[\d]{1,}  ([\d]{1,})  ([\d]{1,})}$/m', $foo, $matches)) {
    $items = array_reduce(
        array_slice($matches, 1),
        fn(array $found, array $match) => array_merge($found, $match),
        []
    );
}

var_dump($items);

Gives:

array(6) {
  [0]=>
  string(6) "123456"
  [1]=>
  string(6) "654321"
  [2]=>
  string(6) "123456"
  [3]=>
  string(6) "123456"
  [4]=>
  string(6) "654321"
  [5]=>
  string(6) "123456"
}

https://3v4l.org/n9tRk

Jared Farrish
  • 48,585
  • 17
  • 95
  • 104