Рецепты RegEx

Переменные

Формула RegEx, заключенная в скобки, становится переменной. Содержимое переменной можно при поиске/замене вставить в результат при помощи её номера.

Так, например, если вам нужно найти в html-файле все нумерованные главы, которые заключены в тэги <p> и <strong> и заменить теги на <h1>, то содержимое строки поиска будет следующим:

<p><strong>(Глава \d+)</strong></p>

Код \d — это любая одна цифра от 0 до 9, а + обозначает последовательность цифр любой длины. Это может быть и 5, и 124, и 1000000.

Эта строка найдёт, например, такие строки:

<p><strong>Глава 1</strong></p>
<p><strong>Глава 9</strong></p>
<p><strong>Глава 15</strong></p>
<p><strong>Глава 23</strong></p>

И запомнит содержимое, заключенное в скобках.

В строке замены нам необходимо написать такое:

для VS Code:

<h1>$1</h1>

для Calibre Book Editor:

<h1>\1</h1>

Где $1 или \1 — это вызов переменной. В разных программах вызов переменной может отличаться. Ознакомьтесь с документацией.

В результате мы получим такой код:

<h1>Глава 1</h1>
<h1>Глава 9</h1>
<h1>Глава 15</h1>
<h1>Глава 23</h1>

Поиск любого текста в пределах одной строки

.*?

Например, нам нужно найти текст, который заключен в тэг <span> с классом emphasis и заменить тэг на <em>.

Исходный блок текста:

<p>Писать по-русски книгу о компьютерах - дело вообще неблагодарное. Наш <span class="emphasis">великий и могучий</span> уж очень отторгает иноземные компьютерные словечки.</p>

Строка поиска:

<span class="emphasis">(.*?)</span>

Строка замены (в VS Code):

<em>$1</em>

Результат:

<p>Писать по-русски книгу о компьютерах - дело вообще неблагодарное. Наш <em>великий и могучий</em> уж очень отторгает иноземные компьютерные словечки.</p>

Многострочный поиск любого текста

Часто бывает так, что начальные и конечные маркеры поиска находятся в разных строчках.

Вот, например, типичный код html:

    <blockquote>
        <p>Первая книга на русском языке, посвященная широко распространенному на Западе и практически неизвестному в
            России компьютеру Амига.</p>
        <p>Приводится история создания Амиги, краткое описание архитектуры компьютера и его возможностей. Подробно
            рассмотрены команды операционной системы Амиги и командный язык ARexx.</p>
    </blockquote>

Текст, заключенный в тэг <blockquote>, разбит на несколько строк, и поиск по предыдущей формуле ничего не найдёт. А нам нужно, например, заменить <blockquote> на <div class="bq">.

В этом случае нам на помощь прийдут такие формулы:

START[\s\S\r]*?STOP
START[^\r]*?STOP
START[\w\W]*?STOP

Где START и STOP — это маркеры начала и конца поиска. Это три варианта. Подойдёт любой.

Итак, вот строка поиска (помним про скобки):

<blockquote>([^\r]*?)</blockquote>

И строка замены (в VS Code):

<div class="bq">$1</div>

Но часто в коде бывают вложенные конструкции:

<blockquote>
    <p>Первая книга на русском языке, 
    посвященная широко распространенному 
    на Западе и практически неизвестному в
    России компьютеру Амига.</p>
    <blockquote>
        <p>Приводится история создания Амиги, к
        раткое описание архитектуры компьютера 
        и его возможностей. Подробно рассмотрены 
        команды операционной системы Амиги и 
        командный язык ARexx.</p>
    </blockquote>
</blockquote>

И если пользоваться нашей формулой, то редактор найдёт участок текста между первым <blockquote> и первым </blockquote>. Не очень хорошо.

Обратите внимание на невыделенный blockquote

Обратите внимание на невыделенный </blockquote>

В таком случае нужно воспользоваться другой формулой.

Поиск текста между ближайшим к блоку текста маркером START и маркером STOP:

START(?:(?!START)[\s\S\r])*?STOP

В таком случае строка поиска будет следующей (не забываем про скобки):

<blockquote>((?:(?!<blockquote>)[\s\S\r])*?)</blockquote>

В этом случае поиск нужно будет произвести несколько раз.

Ещё раз про скобки: Внимательно следите за скобками. Сколько открыли, столько и закрыли.