Ну писать все 50 вариантов не обязательно. Если подумать, то на ум приходит забавный такой трюк с метасимволом \G и preg_match_all
PHP:
preg_match_all('~<div class="ok">|\G(?!\A)<span>([^<]+)</span>~', $str, $match);
print_r($match[1]);
Метасимвол \G совпадает с позицией, в которой завершилось предыдущее совпадение. Это позволяет собрать все теги span идущие сразу за <div class="ok">.
Там в результатах будет пустой первый элемент это после нахождения <div class="ok">. Легко удаляется array_shift().
PS: Подсветка на regex101.com работает норм. Там по умолчанию в качестве разделителя косая черта и её тогда нужно экранировать в регулярке <\/span>. Жмакни по разделителю что перед строкой и выбери из списка другой.