Регулярные выражения в InDesign

В 2007 году версия Adobe InDesign CS3 приподнесла нам много приятных сюрпризов, в числе которых была поддержка регулярных выражений.

Надо отметить, что эту тему максимально подробно мы разбираем на курсе «Расширенные возможности InDesign».

О регулярных выражениях.

Регулярные выражения (Regular Expression, или RegExp) имеют достаточно длинную историю (самые ранние  практические применения  еще в 70-х годах – в текстовом редакторе Ed в системе UNIX, более поздние – в Perl, Apache, PHP, InDesign ). Они особенно эффективны при выполнении поиска и замены.

В отличие от обычного поиска, где указывается конкретный текст, регулярные выражения позволяют обобщить условия поиска с помощью системы шаблонов. Шаблоны – это текстовые фрагменты, которые содержат как обычные символы, так и метасимволы, с помощью которых задаются специальные функции: альтернативные варианты поиска, условия повторений и пр. Понять, как работает система шаблонов вполне возможно, хотя иногда непросто, так как задачи бывают весьма заковыристые. Для полноценного описания работы шаблонов понадобится слишком много места, поэтому для всех интересующихся приведены ссылки в конце статьи. Здесь же мы разберём ряд задач, которые помогут понять работу системы шаблонов, а также пригодятся при работе с текстом в InDesign.

Для выполнения всех задач используется операция Edit > Find/Change (Поиск и замена) и закладка GREP(регулярные выражения).

Задача №1. Автоматическая расстановка переносов в текстах, содержащих и кириллицу, и латиницу.

Проблема заключается в том, что для работы системы переносов нужно в параметрах символов задать для кириллицы русский язык, а для латиницы – английский. Делать это вручную весьма трудоёмко. Как это сделать автоматически?

Решение:
в строке поиска задать: “[a-zA-Z]” (без кавычек);
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать нужный язык: английский.

Объяснение.

Вначале следует выделить весь текст и задать для него русский язык.

Затем выполнить поиск всех символов латиницы и задать для них английский язык. Для этого в строке поиска ввести шаблон альтернативного выбора символа, который выглядит как набор символов, заключённый в квадратные скобки. Так, шаблон “[abc]” ищет символы “a”, “b” или “с”, шаблон [0-9] – все цифры, а для поиска всех символов латиницы зададим шаблон  “[a-zA-Z]” – в нём перечисляются символы как в нижнем, так и в верхнем регистре. А вот так выглядит шаблон для поиска символов кириллицы: “[а-яА-Я]”.

И всё! В качестве пояснения приведён рисунок:

Задача №2. Поиск слова и всех его форм. Например, для задания оформления полужирным. Решим эту задачу на примере какого-то конкретного слова, например, “пример”.

Решение:
в строке поиска задать: “\<(?i)приме(р|ры|ров|ре|ра)\>”
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать оформление полужирным.

Объяснение.

Во-первых, нужно вычислить все формы этого слова. В нашем случае это будут: “пример”, “примеры”, “примеров”, “примера”, “примеру”, “примере” (кроме “например”, “примерный” и пр. – это уже другие слова).

На этот раз нам нужно задать альтернативные варианты не для символов, а для слов. Такая возможность в шаблонах предусмотрена и реализуется путём перечисления через символ “|” (вертикальная черта). То есть строка поиска должна содержать: “пример|примеры|примеров|примере|примера”

Однако такой поиск игнорирует слова с заглавной буквы! Чтобы решить эту проблему нужно в строку поиска ввести метасимвол “(?i)”, который заставит при поиске игнорировать регистр. И теперь строка поиска выглядит так: “(?i)пример|примеры|примеров|примере|примера”. Не беспокойтесь, при выполнении замены регистр будет сохранён.

Но, увы, ещё одна проблема – система находит эти слова внутри других слов («например», «примерный» и пр.), а нам это не нужно! Выход – надо искать слово целиком. Для этого следует обозначить границы слова в строке поиска – начало слова обозначается метасимволами “\<”, а конец – “\>”.  И теперь строка поиска выглядит так:
“(?i)\<пример|примеры|примеров|примере|примера\>”, или  так:
“\<(?i)пример|примеры|примеров|примере|примера\>”

Это уже готовое решение, но его можно записать значительно проще! Обратите внимание, что при перечислении форм меняется только часть слова. Чтобы отделить её от неизменной части используем возможность группировки символов, для чего альтернативные варианты укажем в круглых скобках. Таким образом, вместо “пример|примеры|примеров|примере|примера” можно написать: “приме(р|ры|ров|ре|ра)” или “пример|пример(ы|ов|е|а)”

И теперь строка поиска выглядит, например, так: “\<(?i)приме(р|ры|ров|ре|ра)\>”

Вот! Наконец-то всё работает так, как нужно! Задача №2 решена.

Задача №3. Поиск текста в кавычках, включая кавычки. Например, для оформления курсивом. Это могут быть названия картин (например  «Мечта рыбака»), или что-нибудь ещё.

Решение:
в строке поиска задать: “«.+?»” (без кавычек);
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать оформление курсивом.

Объяснение.

Итак, строка  поиска должна начинаться с кавычек и заканчиваться кавычками. А что между ними? Да что угодно! И для обозначения этого «что угодно» используются метасимволы, а для задания количества —квантификаторы.

В таблице приведены некоторые метасимволы, которые заменяют обычные символы:

Метасимвол

Заменяет

Значение

.   Любой символ
\d [0-9] Цифра
\D [^0-9] Не цифра
\w [A-Za-zА-Яа-я0-9_] Символы образующие «слово» (буквы, цифры и символ подчёркивания)
\W [^A-Za-zА-Яа-я0-9_] Символы не образующие «слово»
\l [a-zа-я] Все символы в нижнем регистре
\u [A-ZА-Я] Все символы в верхнем регистре
\s   Любой пробел
\S   Любой не пробел

И теперь, если известно, что внутри кавычек содержится 5 символов,  строка поиска должна выглядеть так: “«\w\w\w\w\w»”. А если неизвестно?

Тогда нам помогут так называемые квантификаторы – метасимволы, задающие число повторений. Они указываются после символа или метасимвола. В таблице приведены некоторые квантификаторы:

Обозначение

Число повторений

* Ноль или более
+ Одно или более
 ? Ноль или один раз
*? Ноль или более (короткий вариант)
+? Одно или более (короткий вариант)
?? Ноль или один раз (короткий вариант)
{n} n повторений
{n,} n или более повторений
{n, m} Минимум n и максимум m повторений

И вначале кажется, что нам подойдёт комбинация  “«\w+»”. Однако в ней не учитывается наличие пробелов внутри и то, что система может найти текст не до первой закрывающей кавычки, а, например, до второй. Чтобы найти текст только между соседними кавычками, используем короткий вариант: “«\w+?»”. А чтобы найти ещё и пробел (“\s”) внутри, зададим альтернативу: “«[\w\s]+?»”.

Почти всё правильно, однако если мы столкнёмся с названием «Гуси-лебеди», то наш поиск это название проигнорирует. Тогда расширим до максимума набор допустимых символов – используем метасимвол “.” и получим: “«.+?»”. Это и есть долгожданное решение!

Информация для размышления. Но что делать, если помимо названий картин в тексте могут содержаться цитаты и прочие длинные тексты в кавычках? Подумайте сами! А решение смотрите в конце статьи.

Задача №4. Поиск текста в кавычках, НЕ включая сами кавычки. И оформление подчёркиванием  (например  «Мечта рыбака»).

Решение:
в строке поиска задать: “(?<=«).+?(?=»)”
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать оформление подчёркиванием.

Объяснение.

Нам нужно найти текст в кавычках, но не нужно воздействовать на сами кавычки. Для этого в системе шаблонов предусмотрены возможности просмотра текста: просмотра впереди “(?<=)” и просмотра позади“(?=)”. Просматриваемые символы указываются внутри скобок. Символы, указываемые в шаблоне просмотра, не войдут в результат поиска.

Таким образом, строка поиска вместо “«.+?»” будет выглядеть так: “(?<=«).+?(?=»)”.

Задача №5. Соединение фамилии и инициалов неразрывным пробелом.

Решение:
в строке поиска задать: “(\u[А-Яа-я-]+)\s(\u.)\s(\u.)”
в строке замены задать: “$1~S$2~S$3”

Объяснение.

Такого типа задачи проще всего решать путём начального разбиения и последующей компоновки. В шаблонах для этого предусмотрена возможность запоминания результатов поиска. Искомые фрагменты указываются в строке поиска в круглых скобках, а в строке замены к содержимому скобок можно обратиться путём указания “$1” (первые скобки), “$2” (вторые скобки) и т.д. до “$9” (всего в InDesign доступно 9 фрагментов) и скомпоновать с их помощью нужный фрагмент.

Учтём, что фамилия начинается с заглавной буквы, а инициалы состоят из заглавных букв, разделённых точкой и пробелом. Например, так: “Иванов А. Б.”; или так: “Миклухо-Маклай Н. Н.”

В результате шаблон поиска может выглядеть так: “\u[А-Яа-я-]+\s\u.\s\u.”

То есть вначале ищем заглавную букву “\u”, затем ищем комбинацию букв “[А-Яа-я-]+”, затем инициалы “\s\u.\s\u.”.

Но как сюда можно добавить неразрывный пробел? Используем возможность запоминания результатов – элементы шаблона заключим в круглые скобки:
“(\u[А-Яа-я-]+)\s(\u.)\s(\u.)”.

Результат поиска для первых скобок “(\u[А-Яа-я-]+)” будет помещён в “$1” (фамилия), вторых скобок “(\u.)” – “$2”, третьих “(\u.)” – “$3”.

А для компоновки результата в строке замены укажем  “$1~S$2~S$3” (“~S” – это неразрывный пробел)

Задача №6. Поиск и оформление email.

Решение:
в строке поиска задать: “[\l\u\d\._%-]+@[\l\u\d\._%-]+” (без кавычек);
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать нужное оформление.

Объяснение.

Здесь “\l\u\d” означает буквы в верхнем и нижнем регистре и цифры, а “\._%-“ – это символы, которые допустимы в адресах. Обратите внимание, что символ «точка» обозначается в строке поиска как “\.”, так как написание “.” является не «точкой», а метасимволом (см. задачу №3).

Задача №7. Поиск и оформление url (адреса в интернет).

Решение:
в строке поиска задать: “(((ht|f)tps?://|(www|ftp)\.)[^\s\n]+)(?<![\[\]\.,:;!\}\)<-])”
в строке замены ничего не задавать или ввести в неё “$0” (означает найденный текст);
в опциях замены указать нужное оформление.

Объяснение.

Фрагмент “(ht|f)tps?://” ищет название протокола: “http://”, “https://”, “ftp://”. Вспомните, что “s?:” означает, что “s” может быть, а может и не быть.

Фрагмент “(www|ftp)\.” ищет начальные символы адреса – “www.”  или “ftp.”

Таким образом, фрагмент “((ht|f)tps?://|(www|ftp)\.)” ищет начало адреса URL (типа “http://www.”, “www. ”, “http:// ” )

Затем  фрагмент “[^\s\n]+” ищет любые символы, кроме пробелов (“\s”) и перевода строк (“\n”). Таким образом, фрагмент “(((ht|f)tps?://|(www|ftp)\.)[^\s\n]+)” ищет уже полноценный адрес, однако вместе с адресом захватывает и символ справа от адреса – точку, запятую и прочее. Чтобы исключить эти ненужные символы справа, используется фраза “(?<![\[\]\.,:;!\}\)<-])”, которая убирает любой из символов  “[].,;!}<-“. Обратите внимание, что вместо обычного написания некоторых символов (например “.”) используется написание “\.” – это нужно потому, что эти символы при обычном написании выполняют роль метасимволов. А чтобы вернуть роль обычных символов, их записывают через “\”.

Заключение

Регулярные выражения очень удобно использовать в скриптах – это позволяет автоматизировать обработку текста. А в InDesign CS4 регулярные выражения можно использовать даже в параметрах абзаца для того, чтобы задавать оформление «на лету»!

Полезные ссылки

Примечание.

Решение к задаче №3: “«.{3,30}»” – задаём длину строки от 3 до 30 символов и тем самым отсекаем длинные фрагменты.

Запись опубликована в рубрике Материалы. Добавьте в закладки постоянную ссылку.