OLEX
Silver Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Шаблоны для веб-типографики Скрипт последовательно перебирает имеющиеся шаблоны поиска, и для каждого из них пытается найти в строке все совпадения. В случае успеха совпавшая часть строки заменяется по правилу, указанному в шаблоне замены. Ниже подробно разобрана работа каждой пары шаблонов. Описания следуют в порядке увеличения сложности; этот порядок не совпадает с последовательностью шаблонов в реальном скрипте. При изменении таблицы правил следует учитывать, что исходная строка подвергается обработке в соответствии со всеми шаблонами, поэтому необходимо следить за тем, чтобы последующие правила не искажали действие предыдущих. Примечание. Далее описано большее число шаблонов, чем в примере из предыдущей статьи. Шаблоны в списке не являются истиной в последней инстанции. Для правильной работы регулярных выражений необходимо установить русскую локаль: Код: use POSIX; POSIX::setlocale (&POSIX::LC_ALL, "ru"); use locale; | Удаление лишних пробелов поиск: ' +' замена: ' ' Сопоставление с таким шаблоном поиска находит в тексте непрерывные последовательности, состоящие из двух или более пробелов. В регулярном выражении всего три символа: два пробела и плюс. Пробелы должны совпасть сами с собой, а символ + указывает на то, что предшествующий ему пробел обязан повториться один или более раз. Найденные последовательности заменяется строкой, содержащей один пробел. Замена дефиса длинным тире поиск: ' - ' замена: ' — ' Последовательность символов пробел-дефис-пробел в большинстве случаев означает, что здесь должно стоять тире. Поскольку тире не должно отрываться от предшествующего текста и появляться на следующей строке, перед ним необходимо поставить неразрывный пробел. Таким образом, шаблон-замена принимает указанный вид. Тире в прямой речи поиск: '^- ' замена: '— ' Особо следует отметить случай замены дефиса тире, когда оно обозначает прямую речь, поэтому появляется в начале строки. Чтобы привязать положение дефиса к первой позиции, достаточно поставить перед ним символ ^. Естественно, что в шаблоне-замене неразрывный пробел уже не нужен. Открывающие кавычки поиск: '\s"(\S)' замена: ' «$1' Здесь впервые встретились особые переменные, имя которых состоит только из цифр. После сравнения с шаблоном такие переменные получают значения, соответствующие фрагментам регулярного выражения, заключенным в круглые скобки. Шаблон поиска начинается с метасимвола \s, совпадающего с пробелом, табуляцией или символом перевода строки (последнее совпадение вызвано тем, что во время подстановки шаблона включается многострочный режим из-за наличия модификаторов /gm). Далее следует символ дюйма, который будет заменен левой кавычкой-«елочкой», а после этого в скобках стоит метасимвол \S, он совпадает с любым символом, который не входит в набор символов, совпадающих с \s. Иными словами, весь шаблон совпадет, если найдется любой символ, слева от которого стоят пробел и символ дюйма. Строка замены формируется из пробела, символа левой кавычки («) и значения переменной $1, в которой окажется символ, следующий за кавычкой. Пару шаблонов для расстановки кавычек можно несколько изменить, чтобы они правильно реагировали на кавычки, появившиеся в начале строки: поиск: '(^|\s)"(\S)' замена: '$1«$2' В отличие от предыдущего случая, теперь символ дюйма может появиться как после пробела (или табуляции или перевода строки), так и в начале строки. Возможность выбора в регулярных выражениях обозначают вертикальной чертой. Для того, чтобы ограничить действие зоны выбора, поставлены круглые скобки. Однако новые скобки приведут и к дополнительной переменной $2 (именно в нее будет записан символ, следующий после кавычки). Поэтому следует изменить и шаблон-замену. Закрывающие кавычки поиск: '(\S)"([ .,?!])' замена: '$1»$2' Поиск открывающих и закрывающих кавычек имеет общие черты, за исключением того, что шаблоны поиска для этих случаев почти зеркально повторяют друг друга. Перед кавычкой должен быть непробельный символ, а после — пробел или знак препинания. Поэтому в регулярном выражении появился символьный класс [ .,?!]. Такая конструкция совпадает с одним (и только одним) из символом, указанных в квадратных скобках. В шаблоне замены вновь присутствуют переменные $1 и $2, а между ними помещен код правых кавычек. Как и ранее, допустимо включить в шаблон символ конца строки $, указав его как альтернативу символьному классу: поиск: '(\S)"([ .,?!]|$)' замена: '$1»$2' Примечание. Если оба аргумента оператора выбора | — единичные символы, то конструкции a|b и [ab] эквивалентны. В обоих случаях шаблон совпадет с каким-либо из двух указанных символов. Однако, если в списке присутствует символ конца строки, следует пользоваться только оператором |. Диапазоны численных значений поиск: '(\d)-(\d)' замена: '$1–$2' Диапазон значений обычно указывают либо с помощью тире, либо многоточием. Если между двумя цифрами (именно цифрами, а не обязательно числами) стоит дефис, скорее всего здесь записан интервал, и дефис следует изменить на среднее или длинное тире (по вкусу). Совпадение с цифрой выполняет метасимвол \d. Кстати, вместо него можно записать символьный класс [0123456789], или в сокращенной записи, [0-9]. Многоточие поиск: '\.{3}' замена: '…' Для обозначения многоточия существует особый символ …. Регулярное выражение ищет последовательности из трех точек. Сам символ «точка» в регулярных выражением означает совпадение с любым символом, поэтому его необходимо экранировать обратным слэшем. Квантификатор {3} указывает, что предыдущий символ должен повториться ровно три раза. Слова, написанные через дефис поиск: '(\S+)-(\S+)' замена: '<nobr>$1-$2</nobr>' Двойные слова (например, «по-русски», «два-три») обычно лучше смотрятся, если они не разрываются на месте дефиса. Чтобы избежать переноса на новую строку, достаточно обрамить такие слова тегами <nobr>…</nobr>. В шаблоне поиска две одинаковые конструкции (\S+), которые совпадают с двумя разделенными дефисом последовательностями непробельных символов. Найденные слова попадают в переменные $1 и $2. Неразрывный пробел после инициалов поиск: '(\w\.)\s(\w\.)\s(\w\w+)' замена: '$1 $2 $3' Инициалы можно определить, если после одиночной буквы (она совпадает с метасимволом \w) стоят точка и пробел. Приведенное выше регулярное выражение помещает в переменные \$1 и $2 инициалы (вместе с точками), а в переменную $3 — фамилию. Шаблон-заменитель соединяет найденные подстроки неразрывными пробелами. Полезно предусмотреть также шаблон, в котором указан только один инициал: поиск: '(\W\w\.)\s(\w\w+)' замена: '$1 $2' Неразрывный пробел после цифр поиск: '(\d)\s' замена: '$1 ' Поведение регулярных выражений аналогично расстановке пробелов после инициалов. Неразрывный пробел после коротких слов my $preps = "я|ты|мы|вы|не|ни|на|но|в|во|до|от|и|а|ее|". "он|с|со|о|об|ну|к|ко|за|их|из|ей|ой|ай"; поиск: "(\\s|^)((?:$preps)[.,]?)\\s", замена: '$1$2 ' Слова, состоящие из одной или двух букв, обычно желательно переносить на новую строку вместе с последующими словами. (Кроме случая, когда такое слово стоит в конце строки: здесь лучше переносить на новую строку два последних слова.) Следует различать предлоги, местоимения и некоторые другие слова от частиц типа «ли» (последние желательно оставлять на одной строке с предшествующим словом или переносить их оба). Список коротких слов записан в переменной $preps через символ выбора. Отдельная переменная сделана не случайно — далее ее можно повторно применять в других регулярных выражениях. Кроме того, они становятся проще и логичнее. Обратите внимание, шаблон замены заключен в двойные кавычки, поэтому Perl подставляет в него значение переменной $preps. По этой же причине теперь следует экранировать символ обратного слеша. Рассмотрим шаблон подробнее. Вначале стоит знакомая конструкция (\s|^), совпадающая с пробелом или началом строки. В конце шаблона указан метасимвол \s, который потребует пробел в исходной строке. Осталось разобрать подшаблон ((?:$preps)[.,]?). Во-первых, на место переменной $preps подставляется строка альтернатив, определенная ранее. После нее указан символьный класс [.,], совпадающий либо с точкой, либо с запятой. Наличие одного из этих символов не обязательно: об этом говорит квантификатор ?. Если символьный класс поместить непосредственно после переменной, Perl станет интерпретировать последовательность $preps[.,] как элемент массива @preps с индексом [.,], что вызовет ошибку на этапе компиляции программы. Поэтому следует отделить левую квадратную скобку от имени переменной. Это можно сделать так: ($preps)[.,]. Теперь ошибка не возникнет, но появится дополнительная переменная $n. Чтобы скобки выполняли только функцию группировки, указан модификатор ?:, в этом случае совпавшее внутри круглых скобок выражение не будет копироваться в отдельную переменную. Наконец, можно выполнять замену. Значимые части выражения содержатся в переменных $1 и $2, а после них следует поставить неразрывный пробел . Пробелы около двух коротких слов поиск: "(\\s|^)((?:$preps)[., ]\\s?(?:$preps)[.,]?)\\s(\\S+)", замена: '$1<nobr>$2 $3<\/nobr>', Если подряд идут два коротких слова, ранее описанный шаблон распознает только одно из них. Чтобы обработать последовательности из двух коротких слов и следующего за ними слова, в шаблон для поиска следует вставить еще одну конструкцию ((?:$preps)[., ]), за которой возможно последуют пробелы. В конце всего выражения делается попытка отыскать следующее слово. Неразрывный пробел перед короткими частицами my $posts = "ли|ль|же|ж|бы|б"; поиск:"(\\S+)\\s($posts(?:[ .,!?]))", замена: '$1 $2' Это правило размещает неразрывный пробел непосредственно перед любым из вариантов слов, перечисленных в переменной $posts. В остальном работа шаблонов аналогична происходящему в двух предыдущих случаях. © http://regexp.ru |