- array_map: documentation ( source)
- preg_match_all: documentation ( source)
- implode: documentation ( source)
- explode: documentation ( source)
- array_unique: documentation ( source)
<?php
$re = '/^(#\h*)((\[\d+]|\{\d+}|\(\d+\))(?:\h+(?3))*)$/m';
$str = '# [1] {1} [2] {10} [3] [3] [4] {10} {100} [1] [5]
# [5] {1} [6] (10) (20) (10) {10} [7] [5] [6] {10} {100} [8] [5] (10) (30)
# (10) (30) [7] {1} [8] {10} [9] [7] [8] {100} {101} [9] [5] {101} (50)';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
echo implode("\n", array_map(fn($x) => $x[1] . implode(' ', array_unique(explode(' ', $x[2]))), $matches));