Это должно сработать, оно захватывает уникальные значения только один раз:
(\d+)(?:_)(?![\s\S]*\1)
Попробуйте демо здесь
Объяснение
(\d+)(?:_)(?![\s\S]*\1)
1-я группа захвата (\d+)
\d+
соответствует цифре (равно [0-9]
)
- Квантификатор - сопоставляет от одного до неограниченного количества раз, насколько это возможно, и возвращает по мере необходимости (жадный)
Группа без захвата (?:_)
_
соответствует символу _
буквально (с учетом регистра)
Отрицательный взгляд вперед (?![\s\S]*\1)
Утверждают, что приведенное ниже регулярное выражение не соответствует
Соответствует одному символу, представленному в списке ниже [\s\S]*
- Квантификатор - сопоставляет от нуля до неограниченного числа раз столько раз, сколько возможно, возвращая при необходимости (жадный)
\s
соответствует любому пробелу (равен [\r\n\t\f\v ]
)
\S
соответствует любому непробельному символу (равному [^\r\n\t\f\v ]
)
\1
соответствует тому же тексту, что и последний сопоставленный первой группе захвата