Программирование на языке Ruby.

3.13.4 Позитивное и негативное оглядывание назад.

Если заглядывания вперед вам недостаточно, то Oniguruma предлагает еще и оглядывание назад, позволяющее определить, предшествует ли текущему положению заданный образец.

Как и многое другое в регулярных выражениях, эту возможность довольно трудно понять и обосновать. Спасибо Эндрю Джексону за следующий пример.

Предположим, что вам нужно проанализировать некоторую генетическую последовательность (молекула ДНК состоит из четырех основных белков, которые обозначаются А, С, G и T.) Допустим, что мы ищем все неперекрывающиеся цепочки нуклеотидов (длины 4), следующие за T. Нельзя просто попытаться найти T и взять следующие четыре символа, поскольку T может быть последним символом в предыдущем соответствии.

Gene = 'GATTACAAACTGCCTGACATACGAA'.

Seqs = gene.scan(/T(\w{4})/).

# seqs равно: [["TACA"], ["GCCT"], ["ACGA"]].

Ho в этом коде мы пропустили цепочку GACA, которая следует за GCCT. Позитивное оглядывание назад позволит найти все нужные цепочки:

Gene = 'GATTACAAACTGCCTGACATACGAA'.

Seqs = gene.scan(/(?<=T)(\w{4})/).

# seqs равно: [["TACA"], ["GCCT"], ["GACA"], ["ACGA"]].

Следующий пример - небольшая модификация примера, предложенного К. Косако (К. Kosako). Предположим, что есть текст в формате XML (или HTML), и мы хотим перевести в верхний регистр весь текст вне тегов (то есть cdata) Вот как можно сделать это с помощью оглядывания назад:

Text =<<-EOF.

<body> <h1>This is a heading</h1>

<p> This is a paragraph with some.

<i>italics</i> and some <b>boldface</b>

In it...</p>

</body>

EOF.

Pattern = /(?:^| # Начало или...

   (?<=>)        # текст после '>'.

  )

  ([^<]*)        # И все символы, кроме '<' (запомнены).

 /x.

Puts text.gsub(pattern) {|s| s.upcase }.

# Вывод:

# <body> <h1>THIS IS A HEADING</h1>

# <p>THIS IS A PARAGRAPH WITH SOME.

# <i>ITALICS</i> AND SOME <b>BOLDFACE</b>

# IN IT...</p>

# </body>