Попробуйте это регулярное выражение:
$re = '#\[(?:.*?(?0))*.*?\]#'
Это будет соответствовать паре [...], которая сама может содержать одну или несколько пар [...] с любыми символами между ними. Это делается с помощью рекурсии в шаблоне ((?0)
вызывает шаблон снова).
preg_match($re, '[.[.]....]', $m);
print_r($m);
// Output:
// Array
// (
// [0] => [.[.]....]
// )