1

I have large string block which I need to split into arrays based on if they're wrapped in brackets or separated by new lines.

Input:

[this is block
this is also same "block"
this is same block

another same block]
new block!
another new block!
[this is new block
this is also a new block]

One of the many things I've tried:

$block_lines = preg_split('/\[([^]]+)\]|\r/', $block_content);

Expected result:

Array
(
  [0] => 'this is block
  this is also same "block"
  this is same block

  another same block'
  [1] => 'new block!'
  [2] => 'another new block!'
  [3] => 'this is new block
  this is also a new block'
)

Actual result:

Array
(
  [0] => 'new block!'
  [1] => 'another new block!'
  [2] => ''
)
4
  • 1
    I don't recommend preg_split() for this because you need to pair the [ with the ]. Commented Dec 20, 2018 at 22:56
  • It looks like you are using curly braces instead of square braces in your pattern. \R will get \r\n and \n. Commented Dec 20, 2018 at 23:04
  • To start this \{ will not match [ , it just won.t. In other words \{([^}]+)\} matches {tag} not [tag] Commented Dec 20, 2018 at 23:05
  • Yeah sorry about that, I tried doing a variation with curly braces in case I was getting confused with the multiple square brackets. Edited it back to the version I was trying with square brackets (still incorrect), but I've accepted the correct answer below. Commented Dec 20, 2018 at 23:15

3 Answers 3

2

You can use this regex in preg_split:

/\[([^]]+)]|\R/

It splits the string on either a string of characters inside [ and ], or on a newline. By using the PREG_SPLIT_DELIM_CAPTURE flag, we can capture the contents of the [] as well:

$string = '[this is block
this is also same "block"
this is same block

another same block]
new block!
another new block!
[this is new block
this is also a new block]';
print_r(preg_split('/\[([^]]+)]|\R/', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE));

Output:

Array ( 
    [0] => this is block 
this is also same "block" 
this is same block

another same block
    [1] => new block!
    [2] => another new block!
    [3] => this is new block
this is also a new block
)

Demo on 3v4l.org

Sign up to request clarification or add additional context in comments.

Comments

1

Match all square braces matches first (which may contain new lines) else match a single line.

The reason that I am favoring preg_match_all() over preg_split() for this case is because in plain terms, you aren't actually intending to perform dynamic explosions but to find matches.

Code: (Demo)

$text = '[this is block
this is also same "block"
this is same block

another same block]
new block!
another new block!
[this is new block
this is also a new block]';

var_export(preg_match_all('~\[[^\]]*]|.+~', $text, $matches) ? $matches[0] : 'nothing');

Output:

array (
  0 => '[this is block
this is also same "block"
this is same block

another same block]',
  1 => 'new block!',
  2 => 'another new block!',
  3 => '[this is new block
this is also a new block]',
)

Comments

0

Alternatively, to change the phrasing of your logic, you wish to explode on all newlines that are not inside of a square bracketed expression. You can use (*SKIP)(*FAIL) to match and disregard the bracketed expressions, and explode on all newlines that make it through the filter.

Code: (Demo)

var_export(preg_split('~\[[^\]]*](*SKIP)(*FAIL)|\R~', $text));

Output:

array (
  0 => '[this is block
this is also same "block"
this is same block

another same block]',
  1 => 'new block!',
  2 => 'another new block!',
  3 => '[this is new block
this is also a new block]',
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.