Поиск вырожденных последовательностей в структурах ДНК с использованием регулярных выражений

Есть задачи для сервера - искать определенные последовательности в структуре ДНК. Они ставятся по-разному: иногда нужно найти ближайшую последовательность, иногда - все возможные, но чаще всего - найти первую и последнюю.

Если упростить, то есть длинная строка (не менее 8 тысяч символов, алфавит - A, G, T, C) и короткие (не более 12 символов) строки, которые нужно искать. Если строка не вырождена (пример: AACGTT), то задача проста - strpos() и strrpos() дают нормальный по скорости результат, а, главное, - сам результат.

Но если строка вырождена, например, AAWWTT, где W - это C или G, или ещё хуже - CCN(7)GG, где N(7) - это 7 любых символов A, G, T или С, то, как я понимаю, проще всего идти через, например, preg_match_all().

$dna = "AGTC......GTC"; //ДНК-последовательность, длинная строка, берётся из базы, в ней практически гарантированно есть наши искомые строки
$pattern1 = "AA(C|G){2}TT"; // AAWWTT
$pattern2 = "CC.{7}GG"; // CCN(7)GG
$matches = array(); // тут будут результаты

теперь, если просто запустить

if (preg_match_all($pattern1,$ldna,$matches,PREG_OFFSET_CAPTURE) === false) 
// PREG_OFFSET_CAPTURE используем, чтобы получить позиции 

{
// не нашли - обрабатываем ситуацию, она редка
}
else {
    $k1 = $matches[count($matches)-1][1];
}

то имеем две ошибки: "Undefined offset" - это, видимо, из-за того, что массив $matches у нас пуст, поэтому count() к нему неприменимо

и "preg_match_all(): Delimiter must not be alphanumeric or backslash" - а вот с этой ошибкой я не могу разобраться. Я неправильно использую preg_match_all()? Или я так и не научился строить регулярные выражения?


Ответы (1 шт):

Автор решения: teran

паттерн заключается в разделители. обычно это /. То есть /AA(C|G){2}TT/.

Если вам группы захвата сами не нужны, и достаточно будет поиска позиции вхождения, то группы захвата мб не стоит писать. либо использовать non-capturing.

$pattern1 = "/AA([CG]{2})TT/";   // AAWWTT
$pattern2 = "/CC([AGTC]{7})GG/"; // CCN(7)GG

точка используется как любой символ. поскольку ваш алфавит ограничен (пусть и других в строке не встретится), возможно,будет более эффективно использовать не .{7} а [AGTC]{7}, но этот вопрос лучше проверить на практике.

что касается первой ошибки, то сделайте print_r($matches) чтобы уточнить по правильным ли индексам обращаетесь.

→ Ссылка