regex to match line breaks and tabs between brackets

Viewed 173

I'm trying to remove line breaks and tabs from content that's inside brackets from data like this:

settings:a [
    a:[
        a:a
        b:b
    ]
    b:[
        a:a
        b:b
    ]
]

settings:b [
    a:[
        a:a
        b:b
    ]
]

So it becomes:

settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ] 
settings:b [ a:[ a:a b:b ] ]

The regex i'm using \n(?=[^\[\]]*\]) works to some extent but I don't get the output like above. Can you help?

Regex Example

2 Answers

You may use this recursive regex in preg_replace_callback:

$s = 'settings:a [
    a:[
        a:a
        b:b
    ]
    b:[
        a:a
        b:b
    ]
]';

echo preg_replace_callback('/\[(?:([^][]*)|(?R))*\]/', function ($m) {
      return preg_replace('/\s+/', ' ', $m[0]); }, $s) . "\n";

Output:

settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ]

RegEx Demo

You can use the following regex with preg_replace (so, a single regex pass will do):

[\t\n]+(?=[^][]*(?:(\[(?:[^][]++|(?1))*])[^][]*)*])

See the regex demo. Details:

  • [\t\n]+ - one or more tab or newline chars (use \s if you need to match any whitespace, and also add u modifier flag if you need to handle Unicode texts)
  • (?=[^][]*(?:(\[(?:[^][]++|(?1))*])[^][]*)*]) - a positive lookahead that requires its patterns to match immediately to the right of the current location:
    • [^][]* - zero or more chars other than [ and ]
    • (?:(\[(?:[^][]++|(?1))*])[^][]*)* - zero or more occurrences of
      • (\[(?:[^][]++|(?1))*]) - Group 1 (technical, necessary for recursion to work): a [, then any substring between paired nested [ and ] and then a ]
      • [^][]* - zero or more chars other than [ and ]
    • ] - a ] char.

See PHP demo:

$re = '/[\t\n]+(?=[^][]*(?:(\[(?:[^][]++|(?1))*])[^][]*)*])/';
$str = "settings:a [\n  a:[\n       a:a\n       b:b\n   ]\n b:[\n       a:a\n       b:b\n   ]\n]\n\nsettings:b [\n  a:[\n   \n\na:a\n       b:b\n   ]\n]";
echo preg_replace($re, ' ', $str);
// => settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ]
//    settings:b [ a:[ a:a b:b ] ]
Related