101 СПОСОБ  ЗАРАБОТАТЬ   НА ПЕЧАТИ

Два загадочных режима GREP-поиска

  • Михаил Иванюшин
  • 13 ноября 2024 г.
  • 112
Если вы при работе в индизайне используете GREP-поиск, то в списке опций поиска наверняка видели режимы со странными названиями «однострочный поиск» и «многострочный поиск». Странными — потому что эти названия совсем не просто соотнести с действиями, выполняемыми при выборе данных режимов. В результате далеко не все пользователи используют эти интересные возможности поиска.

Режимы однострочный (Single-line) и многострочный (Multiline)

Да, в индизайне эти сходные по написанию слова пишутся по-английски именно так: одно слово с дефисом, второе слитно.

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

Состояние режима «однострочный» влияет на обработку метасимвола . («точка» — совпадение с любым символом). Режим «многострочный» определяет обработку маркеров положения: ^ (начало абзаца) и $ (конец ­абзаца).

Когда однострочный режим выключён, поиск с использованием метасимвола . (точка) выполняется в пространстве абзаца, в котором стоит курсор. Аналогия — каждый абзац в статье является отдельной строкой. Когда однострочный режим активен, поиск с использованием метасимвола . (точка) выполняется в пространстве всей статьи. Статья превращается в одну ­строку.

Однострочный режим

(?-s) однострочный режим выключен, это стандартное состояние обработки греп-запросов: оператор .* выбирает все символы, начиная от текущей позиции до конца абзаца, но сам конец абзаца в выборку не попадает.

(?s) одиночный режим включён, в выборку попадает и знак перевода строки. Т. е. будет выбран весь текст от точки курсора до конца статьи. А если курсор не в тексте, а выбран фрейм, то будет выбрана вся статья.

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

Многострочный режим

(?m) многострочный режим включён, это стандартное состояние обработки греп-запросов, знаки ^ и $ определяют начало и конец абзаца.

(?-m) многострочный режим выключен, знак ^ интерпретируется как \A — маркер начала статьи, а знак $ как \Z — маркер конца статьи.

Важно: если в тексте запроса нет метасимволов ^ и $, то не имеет значения, какой вариант многострочного режима сейчас установлен.

Совместное использование режимов

Если в тексте запроса есть точка и хотя бы один из двух знаков ^ или $, то можно определить, как эти режимы будут взаимо­действовать.

Очевидно, что возможны четыре их сочетания

Два загадочных режима GREP-поиска

Допустим, есть такие запросы поиска .{10}$ и ^.{12} и вот такой текст:

123456789ABCDEF

123456789ABCDEF

12345678

123456789ABCDEF

123456789ABCDEF

Поиск всегда начинается с текущей позиции курсора.

(?s)(?-m).{10}$ Будут выбраны последние десять знаков статьи. Поскольку точка работает как любой знак, то если последним символом статьи будет перевод строки, то он тоже попадёт в выборку.

(?-s)(?-m).{10}$ Если последний знак статьи не является переводом сроки, то будут выбраны последние десять знаков статьи. И т. к. точка работает как печатный знак, то если последним символом статьи будет перевод строки, то ничего выбрано не будет, поскольку среди последних десяти символов есть знак перевода строки, а он не входит в множество знаков, охватываемых метасимволом точка.

(?m)(?-s).{10}$ Будут выбираться последние десять знаков каждой строки. Перевод строки в выборку не входит.

(?sm).{10}$ Если поставить курсор в начало тестового текста, то будут выбираться последние десять знаков каждой строки. Но если, например, поставить курсор после буквы A во второй строке, то запрос выделит следующие десять знаков: буква F, перевод строки и восемь цифр третьей строки. Почему так происходит? Запрос ищет конец абзаца; находит его в конце строки, где он стоит; оценивает число знаков перед этим концом абзаца не только на предмет, есть ли нужное число, но и где находится текущая точка вставки. В нашем случае точка вставки попадает в эти десять знаков, значит, этот перевод строки не подходит. Он ищет следующий, так же проверяет десять символов перед ним, не попадает ли в них текущая позиция курсора. Если нет, то они выделяются.

В этом примере мы поставили курсор после буквы A. Такой же результат будет до буквы F. Но как только курсор после F, он попадает в пространство десяти знаков перед переводом строки, и запрос ищет в тексте следующий перевод строки.

(?s)(?-m)^.{12} Поиск в статье, ищутся все знаки в тексте. Знак ^ интерпретируется не только как начало абзаца , но и как \r, поэтому этот запрос последовательно выделяет сперва 12 знаков с начала статьи, а потом все последовательности из двенадцати знаков, начинающихся с \r.

(?-s)(?-m)^.{12} Поиск в статье, любой печатный знак. Поскольку «любой печатный знак», т. е. перевод строки в выборку не попадёт, то этот запрос выберет только первые двенадцать символов первой строки, если длина строки больше 12.

(?m)(?-s)^.{12} Поиск в строке, любой печатный знак.

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

(?sm)^.{12} Поиск в строке, любой знак.

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

Конечно, приведённые примеры вряд ли встретятся в реальной вёрстке. Но они полезны для того, чтобы понять особенности использования этих режимов.

Для понимания

Если есть два абзаца

Фраза

Слово

то любой из запросов .+ или (?-s).+ найдёт сперва абзац Фраза, а потом абзац Слово. В выборке будут только печатные знаки.

А если у нас такой запрос (?s).+, то он будет видеть этот текст так, в виде одной строки:

Фраза\rСлово

и этот запрос выберет все знаки в этой строке.

Строки ^фраза и (?m)^фраза обозначают поиск текста фраза в начале любой строки.

Строки слово$ и (?m)слово$ обозначают поиск текста слово в конце любой строки.

Строка (?-m)^фраза обозначает поиск текста фраза в начале статьи. Строка (?-m)слово$ обозначает поиск текста слово в конце статьи. Очевидно, что эти запросы можно переписать иначе, сделав их более понятными: \Aфраза и слово\Z.

Требуется уточнение

В начале было сказано, и это взято из документации, что состояние многострочный режим включено по умолчанию. Вся ли это информация об этом режиме?

Вот задача: найти каждый первый пробел в абзацах и запрос для её решения: ^(.+?)\K\h

Запрос эту задачу не решает, т. к. идёт через строку, и почему он так ведёт себя, я точно не знаю. Возможно, это особенности реализации нежадного поиска. Но если его изменить: (?m)^(.+?)\K\h, то он будет идти по каждой строке.

В чём же дело? Ведь если многострочный режим включён по умолчанию, то запросы ^(.+?)\K\h и (?m)^(.+?)\K\h должны выполняться одинаково. Однако этого не происходит. Моё предположение, что да, это так, но дополнительно при появлении команды (?m) изменяется трактовка знака ^, он становится на время работы запроса не только маркером начала абзаца, но и соответствует переводу строки \r.

Вот как это выглядит в реализации с другими запросами: запрос \r(.+?)\K\h идёт по всем строкам, начиная с второй, а запрос (^|\r)(.+?)\K\h работает так же, как (?m)^(.+?)\K\h. Точно так же будут работать (?s)^(.+?)\K\h и (?-s)^(.+?)\K\h, именно в силу того, что на время действия запроса операторы включения любого из этих режимов определят, что в запросе метасимвол ^ надо трактовать как \r.

Примеры

• Заменить шпации на табуляции.

В тексте позиции списка разделены концевыми шпациями.

A) text, numbers =КШ= D) text, numbers

B) text, numbers =КШ= E) text, numbers

C) text, numbers =КШ= F) text, numbers

Тут =КШ= — текстовое обозначение концевой шпации.

Надо заменить эти шпации на табуляции.

Запрос ^\u\).+\K~f будет искать через строку.

А явное указание, что многострочный режим включён (хотя он уже был включён по умолчанию), определит на время действия запроса, что символ начала статьи/начала абзаца ^ надо применять и к переводу строки. В результате запрос (?m)^\u\).+\K~f пройдёт по каждой строке.

• Выделить весь текст статьи, независимо от того, где стоит курсор.

Запрос .* выделит текст от текущей позиции до конца абзаца. Поскольку в запросе есть точка, то для расширения области действия запроса надо использовать однострочный режим. От текущей позиции до конца абзаца статьи текст выделит такой запрос (?s).*, а задачу выделения всего текста статьи решит запрос (?s)\A.+ В обоих случаях именно включение однострочного режима позволило включить в выборку знаки перевода строки.

• Выделить текст от позиции курсора до конца статьи.

Задачу выделения текста от позиции курсора до конца статьи решает любой из таких запросов:

(.|[\r\n])+ или (?s).*

Первый вариант для стандартного случая, когда однострочный режим выключен. Второй включает этот режим, и вся статья для поиска .* становится одной строкой.

Заключение

К сожалению, к тому диалекту GREP, что есть в индизайне, на русском языке нет толковой информации от разработчиков. Данная статья — результат моего исследования этих режимов. Когда с ними разобрался, многие задачи поиска стали решаться намного проще.

Попробуйте и вы сделать их своим инструментом, если пока не получалось использовать эти режимы.

Будут вопросы, пишите.

Михаил Иванюшин, независимый автор.

dotextok@gmail.com

https://dotextok.ru

ПОХОЖИЕ СТАТЬИ
Publish молодых

Уже сформировалось убеждение, что полиграфия — не самая привлекательная отрасль для молодых людей, и выражается это старением коллективов типографий — молодёжь к ним не идёт. Для формировании интереса к отрасли при поддержке Publish на базе Московского политехнического университета создаётся студенческий журнал Publish Junior. Подробности о проекте читайте прямо сейчас.

Текстильлегпром 2024

В сентябре в Москве прошла очередная выставка «Текстильлегпром». На этот раз она проходила не на ВДНХ, а в одном из залов выставочного комплекса «Крокус».

Издательство на hand-made маркете

Издательство «Гудвин» — частый гость на всевозможных маркетах и hand-made ярмарках.

Цельное преобразование — прямо сейчас

Когда я с кем-то обсуждаю книгу «Цель» Элияху Голдратта, то часто слышу «а, это про “бутылочные горлышки”, да-да, очень познавательно». Но, на мой взгляд, книга совсем не про это. Поиск ограничений в системе — это один из методов решения проблем на производстве. Как именно?



Новый номер

Тема номера: С иголочки: всё о брендировании текстиля. RICOH Pro C7500. Скоростной УФ-принтер Artis CX-360G Gen 51. Текстильлегпром 2024. Кто побеждает в борьбе: DTG или DTF? День рождение будущего. Agfa Anapurna Ciervo H3200 + Спецпроект Publish Junior



Какой следующий принтер вы купите себе на производство?
    Проголосовало: 15