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

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

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>

Оглавление книги


Генерация: 1.594. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз