Исходя из вашего последнего комментария, возможно, это поможет вам:
(abc|def)(\d+|(?:(?!(?1))[a-z])+)?|((?:(?!(?1))[a-z])+)((?2))?
EDIT. Упс, мне нужно отредактировать мой предыдущий ответ вместо публикации нового.
ИССЛЕДОВАНИЕ:
<?php
$r = '#(abc|def)(\d+|(?:(?!(?1))[a-z])+)?|((?:(?!(?1))[a-z])+)((?2))?#';
$s1 = 'abc20def20ghi20';
$s2 = 'abcdddef20ghi20';
$s3 = 'abcdddef2d0ghi20abcdd';
preg_match_all($r, $s1, $m1);
preg_match_all($r, $s2, $m2);
preg_match_all($r, $s3, $m3);
var_dump($m1[0], $m2[0], $m3[0]);
Выход:
array(3) {
[0]=>
string(5) "abc20"
[1]=>
string(5) "def20"
[2]=>
string(5) "ghi20"
}
array(3) {
[0]=>
string(5) "abcdd"
[1]=>
string(5) "def20"
[2]=>
string(5) "ghi20"
}
array(5) {
[0]=>
string(5) "abcdd"
[1]=>
string(4) "def2"
[2]=>
string(2) "d0"
[3]=>
string(5) "ghi20"
[4]=>
string(5) "abcdd"
}
Как видите, он корректно захватывает все части обеих строк.