sonyps4.ru

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

Структура сетевой операционной системы

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

В сетевой операционной системе отдельной машины можно выделить несколько частей (рисунок 1):

    Средства управления локальными ресурсами компьютера: функции распределения оперативной памяти между процессами, планирования и диспетчеризации процессов, управления процессорами в мультипроцессорных машинах, управления периферийными устройствами и другие функции управления ресурсами локальных ОС.

    Средства предоставления собственных ресурсов и услуг в общее пользование - серверная часть ОС (сервер). Эти средства обеспечивают, например, блокировку файлов и записей, что необходимо для их совместного использования; ведение справочников имен сетевых ресурсов; обработку запросов удаленного доступа к собственной файловой системе и базе данных; управление очередями запросов удаленных пользователей к своим периферийным устройствам.

    Средства запроса доступа к удаленным ресурсам и услугам и их использования - клиентская часть ОС (редиректор). Эта часть выполняет распознавание и перенаправление в сеть запросов к удаленным ресурсам от приложений и пользователей, при этом запрос поступает от приложения в локальной форме, а передается в сеть в другой форме, соответствующей требованиям сервера. Клиентская часть также осуществляет прием ответов от серверов и преобразование их в локальный формат, так что для приложения выполнение локальных и удаленных запросов неразличимо.

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

Рис. 1. Структура сетевой ОС

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

Сетевые операционные системы имеют разные свойства в зависимости от того, предназначены они для сетей масштаба рабочей группы (отдела), для сетей масштаба кампуса или для сетей масштаба предприятия.

    Сети отделов - используются небольшой группой сотрудников, решающих общие задачи. Главной целью сети отдела является разделение локальных ресурсов, таких как приложения, данные, лазерные принтеры и модемы. Сети отделов обычно не разделяются на подсети.

    Сети кампусов - соединяют несколько сетей отделов внутри отдельного здания или внутри одной территории предприятия. Эти сети являются все еще локальными сетями, хотя и могут покрывать территорию в несколько квадратных километров. Сервисы такой сети включают взаимодействие между сетями отделов, доступ к базам данных предприятия, доступ к факс-серверам, высокоскоростным модемам и высокоскоростным принтерам.

    Сети предприятия (корпоративные сети) - объединяют все компьютеры всех территорий отдельного предприятия. Они могут покрывать город, регион или даже континент. В таких сетях пользователям предоставляется доступ к информации и приложениям, находящимся в других рабочих группах, других отделах, подразделениях и штаб-квартирах корпорации.

Главной задачей операционной системы, используемой в сети масштаба отдела, является организация разделения ресурсов, таких как приложения, данные, лазерные принтеры и, возможно, низкоскоростные модемы. Обычно сети отделов имеют один или два файловых сервера и не более чем 30 пользователей. Задачи управления на уровне отдела относительно просты. В задачи администратора входит добавление новых пользователей, устранение простых отказов, инсталляция новых узлов и установка новых версий программного обеспечения. Операционные системы сетей отделов хорошо отработаны и разнообразны, также, как и сами сети отделов, уже давно применяющиеся и достаточно отлаженные. Такая сеть обычно использует одну или максимум две сетевые ОС. Чаще всего это сеть с выделенным сервером NetWare 3.x или Windows NT, или же одноранговая сеть, например сеть Windows for Workgroups.

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

Итак, следующим шагом в эволюции сетей является объединение локальных сетей нескольких отделов в единую сеть здания или группы зданий. Такие сети называют сетями кампусов. Сети кампусов могут простираться на несколько километров, но при этом глобальные соединения не требуются.

Операционная система, работающая в сети кампуса, должна обеспечивать для сотрудников одних отделов доступ к некоторым файлам и ресурсам сетей других отделов. Услуги, предоставляемые ОС сетей кампусов, не ограничиваются простым разделением файлов и принтеров, а часто предоставляют доступ и к серверам других типов, например, к факс-серверам и к серверам высокоскоростных модемов. Важным сервисом, предоставляемым операционными системами данного класса, является доступ к корпоративным базам данных, независимо от того, располагаются ли они на серверах баз данных или на миникомпьютерах.

Именно на уровне сети кампуса начинаются проблемы интеграции. В общем случае, отделы уже выбрали для себя типы компьютеров, сетевого оборудования и сетевых операционных систем. Например, инженерный отдел может использовать операционную систему UNIX и сетевое оборудование Ethernet, отдел продаж может использовать операционные среды DOS/Novell и оборудование Token Ring. Очень часто сеть кампуса соединяет разнородные компьютерные системы, в то время как сети отделов используют однотипные компьютеры.

Корпоративная сеть соединяет сети всех подразделений предприятия, в общем случае находящихся на значительных расстояниях. Корпоративные сети используют глобальные связи (WAN links) для соединения локальных сетей или отдельных компьютеров.

Пользователям корпоративных сетей требуются все те приложения и услуги, которые имеются в сетях отделов и кампусов, плюс некоторые дополнительные приложения и услуги, например, доступ к приложениям мейнфреймов и миникомпьютеров и к глобальным связям. Когда ОС разрабатывается для локальной сети или рабочей группы, то ее главной обязанностью является разделение файлов и других сетевых ресурсов (обычно принтеров) между локально подключенными пользователями. Такой подход не применим для уровня предприятия. Наряду с базовыми сервисами, связанными с разделением файлов и принтеров, сетевая ОС, которая разрабатывается для корпораций, должна поддерживать более широкий набор сервисов, в который обычно входят почтовая служба, средства коллективной работы, поддержка удаленных пользователей, факс-сервис, обработка голосовых сообщений, организация видеоконференций и др.

Кроме того, многие существующие методы и подходы к решению традиционных задач сетей меньших масштабов для корпоративной сети оказались непригодными. На первый план вышли такие задачи и проблемы, которые в сетях рабочих групп, отделов и даже кампусов либо имели второстепенное значение, либо вообще не проявлялись. Например, простейшая для небольшой сети задача ведения учетной информации о пользователях выросла в сложную проблему для сети масштаба предприятия. А использование глобальных связей требует от корпоративных ОС поддержки протоколов, хорошо работающих на низкоскоростных линиях, и отказа от некоторых традиционно используемых протоколов (например, тех, которые активно используют широковещательные сообщения). Особое значение приобрели задачи преодоления гетерогенности - в сети появились многочисленные шлюзы, обеспечивающие согласованную работу различных ОС и сетевых системных приложений.

К признакам корпоративных ОС могут быть отнесены также следующие особенности.

Поддержка приложений. В корпоративных сетях выполняются сложные приложения, требующие для выполнения большой вычислительной мощности. Такие приложения разделяются на несколько частей, например, на одном компьютере выполняется часть приложения, связанная с выполнением запросов к базе данных, на другом - запросов к файловому сервису, а на клиентских машинах - часть, реализующая логику обработки данных приложения и организующая интерфейс с пользователем. Вычислительная часть общих для корпорации программных систем может быть слишком объемной и неподъемной для рабочих станций клиентов, поэтому приложения будут выполняться более эффективно, если их наиболее сложные в вычислительном отношении части перенести на специально предназначенный для этого мощный компьютер - сервер приложений.

Сервер приложений должен базироваться на мощной аппаратной платформе (мультипроцессорные системы, часто на базе RISC-процессоров, специализированные кластерные архитектуры). ОС сервера приложений должна обеспечивать высокую производительность вычислений, а значит поддерживать многонитевую обработку, вытесняющую многозадачность, мультипроцессирование, виртуальную память и наиболее популярные прикладные среды (UNIX, Windows, MS-DOS, OS/2). В этом отношении сетевую ОС NetWare трудно отнести к корпоративным продуктам, так как в ней отсутствуют почти все требования, предъявляемые к серверу приложений. В то же время хорошая поддержка универсальных приложений в Windows NT собственно и позволяет ей претендовать на место в мире корпоративных продуктов.

Справочная служба. Корпоративная ОС должна обладать способностью хранить информацию обо всех пользователях и ресурсах таким образом, чтобы обеспечивалось управление ею из одной центральной точки. Подобно большой организации, корпоративная сеть нуждается в централизованном хранении как можно более полной справочной информации о самой себе (начиная с данных о пользователях, серверах, рабочих станциях и кончая данными о кабельной системе). Естественно организовать эту информацию в виде базы данных. Данные из этой базы могут быть востребованы многими сетевыми системными приложениями, в первую очередь системами управления и администрирования. Кроме этого, такая база полезна при организации электронной почты, систем коллективной работы, службы безопасности, службы инвентаризации программного и аппаратного обеспечения сети, да и для практически любого крупного бизнес-приложения.

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

В идеале сетевая справочная информация должна быть реализована в виде единой базы данных, а не представлять собой набор баз данных, специализирующихся на хранении информации того или иного вида, как это часто бывает в реальных операционных системах. Например, в Windows NT имеется по крайней мере пять различных типов справочных баз данных. Главный справочник домена (NT Domain Directory Service) хранит информацию о пользователях, которая используется при организации их логического входа в сеть. Данные о тех же пользователях могут содержаться и в другом справочнике, используемом электронной почтой Microsoft Mail. Еще три базы данных поддерживают разрешение низкоуровневых адресов: WINS - устанавливает соответствие Netbios-имен IP-адресам, справочник DNS - сервер имен домена - оказывается полезным при подключении NT-сети к Internet, и наконец, справочник протокола DHCP используется для автоматического назначения IP-адресов компьютерам сети. Ближе к идеалу находятся справочные службы, поставляемые фирмой Banyan (продукт Streettalk III) и фирмой Novell (NetWare Directory Services), предлагающие единый справочник для всех сетевых приложений. Наличие единой справочной службы для сетевой операционной системы - один из важнейших признаков ее корпоративности.

Безопасность. Особую важность для ОС корпоративной сети приобретают вопросы безопасности данных. С одной стороны, в крупномасштабной сети объективно существует больше возможностей для несанкционированного доступа - из-за децентрализации данных и большой распределенности "законных" точек доступа, из-за большого числа пользователей, благонадежность которых трудно установить, а также из-за большого числа возможных точек несанкционированного подключения к сети. С другой стороны, корпоративные бизнес-приложения работают с данными, которые имеют жизненно важное значение для успешной работы корпорации в целом. И для защиты таких данных в корпоративных сетях наряду с различными аппаратными средствами используется весь спектр средств защиты, предоставляемый операционной системой: избирательные или мандатные права доступа, сложные процедуры аутентификации пользователей, программная шифрация.

Контрольные вопросы:

    Какие основные виды кабелей закладываются в проекты локальных вычислительных сетей?

    Какой кабель наиболее подходит для использование на дальние расстояния?

    Какой кабель наиболее подходит для использование на близкие расстояния?

    Перечислить основные типы экранов UTP– кабеля.

    Какие два основных стандарта существуют для распределения пар проводов по контактам разъемов RJ45?

    Какие типы кабелей позволяют работать на скоростях выше 10мbit/sec?

    Назначение коммутатора - switch.

    Назначение концентратора - hub

    Назначение маршрутизатора – router

    Что называют сетевой операционной системой в широком смысле?

    Что называют сетевой операционной системой в узком смысле?

    Перечислить и описать признаки корпоративных ОС.

    Какие несколько частей можно выделить в сетевой операционной системе отдельной машины?

    Что входит в обязанности администратора?

    Перечислить современные сетевые ОС?

Сетевая операционная система (англ. Network operating system) - это операционная система, которая обеспечивает обработку, хранение и передачу данных в информационной сети.

Главными задачами сетевой ОС являются разделение ресурсов сети (например, дисковые пространства) и администрирование сети. Системный администратор определяет разделяемые ресурсы, задаёт пароли, определяет права доступа для каждого пользователя или группы пользователей. Отсюда сетевые ОС делят на сетевые ОС для серверов и сетевые ОС для пользователей.

Существуют специальные сетевые ОС, которым приданы функции обычных систем (например, Windows NT) и обычные ОС (Windows XP), которым приданы сетевые функции. Практически все современные ОС имеют встроенные сетевые функции.

Сетевая операционная система составляет основу любой вычислительной сети. Каждый компьютер в сети в значительной степени автономен, поэтому под сетевой операционной системой в широком смысле понимается совокупность операционных систем отдельных компьютеров, взаимодействующих с целью обмена сообщениями и разделения ресурсов по единым правилам - протоколам. Эти протоколы обеспечивают основные функции сети: адресацию объектов, функционирование служб, обеспечение безопасности данных, управление сетью. В узком смысле сетевая ОС - это операционная система отдельного компьютера, обеспечивающая ему возможность работать в сети.

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

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

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

На выделенных серверах желательно устанавливать ОС, специально оптимизированные для выполнения определенных серверных функций. Поэтому в подобных сетях с чаще всего используются сетевые операционные системы, в состав которых входит нескольких вариантов ОС, отличающихся возможностями серверных частей. Например, сетевая ОС Novell NetWare имеет серверный вариант, оптимизированный для работы в качестве файл-сервера.

В одноранговых сетях все компьютеры равны в правах доступа к ресурсам друг друга. Каждый пользователь может по своему желанию объявить какой-либо ресурс своего компьютера разделяемым, после чего другие пользователи могут его использовать. В таких сетях на всех компьютерах устанавливается одна и та же ОС.

Многопользовательская, многозадачная операционная система, способная функционировать на различных аппаратных платформах. В микроядро ОС UNIX встроен модуль, выполняющий протокол управления передачей/межсетевой протокол (протокол TCP/IP).

- сетевая операционная система, ядро которой разработано на базе операционной системы Unix. Linux распространяется с открытыми исходными кодами и применяется для создания серверов в вычислительных сетях и в Интернете.

- разработанная корпорацией Novell сетевая операционная система, которая использует одноранговую архитектуру или архитектуру клиент-сервер.

- разработанная корпорацией Microsoft сетевая, многозадачная операционная система, поддерживающая архитектуру клиент-сервер. ОС Windows NT существует в виде двух продуктов:

  • Windows NT Server, выполняющий функции сервера;
  • Windows NT Workstation, реализующий задачи клиента.

Сетевой операционной системой признается ОС, которая имеет встроенные возможности для работы с компьютерными сетями. К таким своеобразным возможностям могут относиться:

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

Сетевые операционные системы - пример таких оболочек:

  • Novell NetWare.
  • Многие GNU/Linux системы.
  • Microsoft Windows (95, NT и более поздние).
  • Многие UNIX системы, такие как Solaris, FreeBSD.
  • IOS; ZyNOS компании ZyXEL.

Главными задачами системных ОС являются разделение ресурсов сети (например, дисковых пространств) и ее администрирование. С помощью сетевых функций системный администратор определяет разделяемые ресурсы, задает пароли, определяет права доступа для каждого пользователя или группы пользователей.

Которых приведен выше, имеют деление на:

  • сетевые ОС для серверов;
  • сетевые ОС для пользователей.

Имеются особые ОС такого типа, которым даны функции типичных конструкций (Windows NT) и простые ОС (Windows XP), каковым даны сетевые функции. В настоящее время фактически всегда используемые ОС обладают интегрированными функциями.

Структура общесетевой ОС

Сетевая автооперационная концепция является базой для какой-либо вычислительной системы. Любое вычислительное устройство является самостоятельным в своей работе. Вследствие этого под сетевой ОС в современном значении подразумевается комплекс нескольких единичных ПК, взаимодействующих между собой посредством отправки друг другу информации и распределения ресурсов согласно общим законам — протоколам.

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

Особенности

Следует особо отметить ряд элементов, благодаря которым ОС такого типа может функционировать:

  • распределение временной памяти для управления процессорами в многопроцессорных устройствах;
  • возможность управления удаленными компьютерами.

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

  • блокировки файлов и записей (что является необходимым, когда устройства используют совместно);
  • управления справочниками имен ресурсов сети;
  • обработку запросов допуска к системе файлов и различной информации в удаленной форме;
  • управления очередностями запросов удаленных юзеров к собственным устройствам.

Составные элементы

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

Клиентская часть, кроме того, принимает с других серверов ответы и видоизменяет их в локальные форматы. Поэтому удаленные и локальные запросы воспринимаются приложениями одинаково.

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

Исходя из функций, имеющихся в том или ином компьютере, его ОС может не обладать серверной либо клиентской составляющей.

Примеры сетевых операционных систем первого поколения

Первые сетевые операционные системы выглядели как комплекс имеющейся локальной ОС и сетевой оболочки в виде надстройки над ней. В таком случае локальная ОС обладала минимальным количеством сетевых функций, поскольку их выполнением занималась непосредственно оболочка. Наиболее известной системой такого типа, получившей по всему миру широкое распространение, стала MS DOS. Начиная с третьего дистрибутива этой оболочки, у нее появились такие интегрированные функции, равно как блокирование записей и файлов, требуемые с целью общего допуска к файлам. Аналогичный принцип действия имеют и современные повсеместно используемые сетевые ОС - LANtastic и PersonalWare.

Современные этапы развития

Однако наиболее перспективным является способ разработки сетевых ОС, первоначально специализированных для запуска в сети. Функции таких оболочек интегрированы глубоко в их ключевые системные модули, что гарантирует их логичную слаженность, несложность эксплуатации и обновления, а также хорошую эффективность. Сегодня выделяется много ресурсов именно на то, чтобы совершенствовать такие операционные системы. Примеры программ такого типа - различные дистрибутивы Windows NT компании Microsoft.

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

perlre - регулярные выражения Perl
В этом руководстве описан синтаксис регулярных выражений в языке Perl. Описание того, как практически использовать регулярные выражения в операциях сопоставления с образцом, а также разнообразные примеры на эту тему можно найти в разделах m// и s/// на странице справочного руководства perlop .

ОПИСАНИЕ регулярных выражений

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

Последний обычно называют "модификатор /x", хотя рассматриваемый разделитель может и не быть косой. Фактически, любой из этих модификаторов может быть встроен в регулярное выражение с помощью новой конструкции (?...) . См. ниже.

Сам модификатор /x требует немного более подробного рассмотрения. Он заставляет синтаксический анализатор регулярных выражений игнорировать пробельные символы, не замаскированные обратной косой и не входящие в класс символов. Это можно использовать для разбиения регулярного выражения на (немного) более понятные части. Символ # также рассматривается как метасимвол начала комментария, как в остальном коде на Perl. Взятые вместе, эти возможности делают Perl 5 намного более удобочитаемым языком. См. пример кода для удаления комментариев в программе на C на странице справочного руководства perlop .

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

Шаблоны, используемые при сопоставлении с образцом, являются регулярными выражениями типа используемых в версии 8 библиотеки regexp . (Фактически, соответствующие функции являются производными (хотя и весьма далекими) от свободно распространяемой реализации версии 8, которую выполнил Henry Spencer.) Подробнее см. раздел "Регулярные выражения версии 8" .

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

По умолчанию, символ "^ " гарантированно соответствует только началу строки, а символ "$ " - только концу строки (или позиции перед символом перевода строки в конце), причем Perl выполняет ряд оптимизаций исходя из предположения, что буфер содержит только одну строку. Встроенным переводам строк не будут соответствовать метасимволы "^ " или "$ ". Может, однако, понадобиться рассматривать буфер как многострочный, так чтобы "^ " соответствовал позиции после символа перевода строки в буфере, а "$ " - позиции перед символом перевода строки. За счет незначительного повышения накладных расходов это можно сделать с помощью модификатора /m в операторе сопоставления с образцом. (Старые программы для этого устанавливали $* , но такая практика теряет смысл в Perl 5.)

Чтобы упростить многострочные подстановки, символ ". " никогда не соответствует символу перевода строки, если только не используется модификатор /s , сообщающий Perl о необходимости рассматривать буфер как однострочный, - даже если в нем несколько строк. Модификатор /s также отменяет установку $* , если используется (неудачный) старый код, устанавливающий его в другом модуле.

Распознаются следующие стандартные квантификаторы :

(Если фигурная скобка встречается в любом другом контексте, она рассматривается как обычный символ.) Модификатор "* " эквивалентен {0,} , модификатор "+ " - {1,} , а модификатор "? " - {0,1} . n и m должны иметь целые значения, не превышающие 65536.

По умолчанию, квантифицированный подшаблон - "жадный", т.е. он будет сопоставляться с как можно большим количеством вхождений, при котором остаток шаблона сможет сопоставиться. Все стандартные квантификаторы "жадные", т.к. сопоставляются с максимально возможным количеством вхождений (начиная с данного места). Если необходимо сопоставление с минимально возможным количеством вхождений, после квантификатора необходимо указать "? ".

Учтите, что изменяется не значение квантификаторов, а "вес" , - они будут сопоставляться с наименьшей возможной подстрокой :

Поскольку шаблоны обрабатываются как строки в двойных кавычках, следующие метасимволы тоже будут работать:

\t табуляция
\n перевод строки
\r возврат каретки
\f form feed
\a звуковой сигнал
\e escape (вспомните troff )
\033 восьмеричный символ (вспомните PDP-11)
\x1B шестнадцатеричный символ
\c[ управляющий символ
\l перевести следующий символ в нижний регистр (вспомните vi )
\u перевести следующий символ в верхний регистр (вспомните vi )
\L переводить в нижний регистр до \E (вспомните vi )
\U переводить в верхний регистр до \E (вспомните vi )
\E конец изменения регистра символов (вспомните vi )
\Q маскировать метасимволы regexp до \E

Кроме того, Perl определяет следующие метасимволы :

Учтите, что \w соответствует одному алфавитно-цифровому символу, а не целому слову. Чтобы указать соответствие слову, необходимо использовать \w+ . Метасимволы \w , \W , \s , \S , \d и \D можно использовать при задании классов символов (но не в качестве одной из границ диапазона).

Perl определяет следующие утверждения нулевой длины (zero-width assertions):

Граница слова (\b ) определяется как точка между двумя символами, с одной стороны от которой находится \w , а с другой - \W (в любом порядке), считая воображаемые символы начала и конца строки соответствующими \W . (Внутри классов символов \b представляет забой - backspace, а не границу слова.) Метасимволы \A и \Z аналогичны "^ " и "$ ", но не будут сопоставляться несколько раз при использовании модификатора /m , тогда как "^ " и "$ " будут сопоставляться с границей каждой внутренней строки. Чтобы указать соответствие с реальным концом строки, не исключая символ перевода строки, можно использовать \Z(?!\n) .

При использовании скобочной конструкции (...) , \<цифра> соответствует <цифра> -й подстроке. За пределами шаблона всегда используйте перед цифрой "$ " вместо "\ ". (Запись \<цифра> может в редких случаях срабатывать за пределами текущего шаблона, но на это не надо полагаться. См. ниже.) Область действия $ (а также $` , $& и $" ) распространяется до конца охватывающего блока или оцениваемой строки, или до следующего успешного сопоставления с образцом, в зависимости от того, что будет раньше. Если вы хотите использовать скобки для ограничения подшаблона (например, набора альтернатив), не запоминая его как подшаблон, укажите ? после (.

Можно использовать любое количество скобок. Если имеется более 9 подстрок, переменные $10 , $11 , ... будут ссылаться на соответствующую подстроку. В шаблоне \10 , \11 и т.д. ссылаются на уже сопоставленные подстроки, если их уже было столько до этой обратной ссылки. В противном случае (для обратной совместимости) \10 совпадает с \010 , или символом забоя, а \11 совпадает с \011 , символом табуляции. И так далее. (Последовательности от \1 до \9 всегда рассматриваются как обратные ссылки.)

$+ возвращает то, с чем сопоставилась последняя конструкция в скобках. $& возвращает всю сопоставившуюся строку. (Раньше для этого использовался $0 , но больше не используется.) $` возвращает все, что идет до начала сопоставившейся строки. $" возвращает все, что идет после сопоставившейся строки. Примеры:

S/^([^ ]*) *([^ ]*)/$2 $1/; # поменять местами # два первых слова if (/Time: (..):(..):(..)/) { $hours = $1; $minutes = $2; $seconds = $3; }

Обратите внимание, что все метасимволы, предваряемые обратной косой, в Perl - алфавитно-цифровые, например, \b , \w , \n . В отличие от некоторых языков регулярных выражений, здесь обратная косая не предваряет метасимволы, не являющиеся алфавитно-цифровыми. Поэтому все конструкции вида \\ , \(, \) , \< , \> , \{ или \} всегда интерпретируются как литеральные символы, а не как метасимволы. Это упрощает маскировку строки, которую необходимо использовать в качестве шаблона, но которая, как вы опасаетесь, может содержать метасимволы. Просто замаскируйте все не алфавитно-цифровые символы:

$pattern =~ s/(\W)/\\$1/g;

Для этого можно также использовать встроенную функцию quotemeta() . Еще проще замаскировать метасимволы прямо в операторе сопоставления можно следующим образом

/$unquoted\Q$quoted\E$unquoted/

Perl 5 определяет последовательный синтаксис расширений для регулярных выражений. Для этого используется пара круглых скобок, первым символом в которых указан знак вопроса (в Perl 4 это было синтаксической ошибкой). Символ после знака вопроса задает функцию расширения. Поддерживается несколько расширений:

(?#text)

Комментарий. Текст игнорируется. Если использован переключатель /x для вставки форматирующих пробелов, достаточно указать просто # .

(?:regexp) Группирует элементы аналогично "() ", но не создает обратных ссылок, как "() ". Поэтому split(/\b(?:a|b|c)\b/)

аналогично

Split(/\b(a|b|c)\b/)

но не порождает дополнительные поля.

(?=regexp) Положительный просмотр вперед нулевой длины. Например, /\w+(?=\t)/ соответствует слову, после которого идет символ табуляции, но табуляция не включается в $& .
(?!regexp) Отрицательный просмотр вперед нулевой длины. Например, /foo(?!bar)/ соответствует любому вхождению "foo ", за которым не идет "bar ". Учтите, однако, что просмотр вперед и просмотр назад - НЕ одно и то же. Нельзя использовать эту конструкцию для поиска назад: /(?!foo)bar/ не найдет вхождение "bar ", перед которым не идет "foo ". Так происходит потому, что (?!foo) означает, что дальше не должна идти строка "foo " -- а она и не идет, идет "bar ", поэтому "foobar " будет соответствовать этому шаблону. Необходимо задавать что-то вроде /(?foo)...bar/ . "Вроде" - потому, что перед "bar " может и не быть трех символов. Этот случай можно охватить следующим образом: /(?:(?!foo)...|^..?)bar/ . Иногда все же проще написать: if (/foo/ && $` =~ /bar$/)
(?imsx) Один или несколько встроенных модификаторов сопоставления с образцом. Это особенно полезно для шаблонов, заданных в отдельной таблице, когда некоторые из них должны учитывать регистр символов, а другие - нет. Для учитывающих регистр символов достаточно просто включить (?i) перед шаблоном. Например: $pattern = "foobar"; if (/$pattern/i) # более гибкий способ: $pattern = "(?i)foobar";
if (/$pattern/)

Знак вопроса для этого и новой конструкции минимального сопоставления был выбран потому, что 1) знак вопроса редко встречался в прежних регулярных выражениях и 2) когда вы видите знак вопроса, надо остановиться и "спросить" себя, что же на самом деле происходит. Это психология...

Регулярные выражения: Поиск с возвратом

Фундаментальное свойство сопоставления регулярных выражений связано с понятием, которое называется поиск с возвратом (backtracking) и используется (при необходимости) всеми квантификаторами регулярных выражений, а именно * , *? , + , +? , {n,m} и {n,m}? .

Чтобы регулярное выражение сопоставилось с образцом, оно должно сопоставиться целиком, а не только частично. Поэтому если начало шаблона, содержащего квантификатор, успешно сопоставилось так, что остаток шаблона не сопоставляется, механизм сопоставления возвращается назад и перевычисляет начальную часть -- вот откуда и название "поиск с возвратом".

Вот пример поиска с возвратом: предположим, необходимо найти слово, идущее после "foo " в строке "Food is on the foo table. ":

$_ = "Food is on the foo table."; if (/\b(foo)\s+(\w+)/i) { print "$2 follows $1.\n"; }

При выполнении сопоставления для первой части регулярного выражения (\b(foo) ) найдется возможное соответствие прямо в начале строки, при этом в $1 будет помещено значение "Foo ". Однако, как только механизм сопоставления увидит, что после сохраненного в $1 значения "Foo " нет пробела, он поймет свою ошибку и начнет снова со следующего символа после неудавшегося сопоставления an. В этот раз он пройдет до следующего вхождения "foo ". Все регулярное выражение в целом теперь сопоставляется и будет получен ожидаемый результат, "table follows foo. ".

Иногда минимальное сопоставление может оказаться очень полезным. Предположим, необходимо найти все, что идет между строками "foo " и "bar ". Сразу можно написать что-то вроде:

$_ = "The food is under the bar in the barn."; if (/foo(.*)bar/) { print "got <$1>\n"; }

Что, возможно, неожиданно, выдает:

Got

Так произошло потому, что шаблон .* был жадным, вот вы и получили все от первого "foo " до последнего "bar ". В этом случае более эффективно использовать минимальное сопоставление, гарантирующее, что вы получите текст между "foo " и первым же вхождением "bar " после него.

If (/foo(.*?)bar/) { print "got <$1>\n" } got

Вот другой пример: пусть необходимо найти число в конце строки и сохранить предыдущую сопоставившуюся часть. Вы пишете следующее:

$_ = "I have 2 numbers: 53147";
if (/(.*)(\d*)/) { #Ошибка! print "Beginning is <$1>, number is <$2>.\n"; }

Это вообще не сработает, поскольку шаблон .* был жадным и поглотил всю строку. Поскольку \d* может соответствовать пустой строке, все регулярное выражение в целом успешно сопоставляется.

Beginning is , number is <>.

Вот еще несколько вариантов, большинство из которых не сработает:

$_ = "I have 2 numbers: 53147"; @pats = qw{ (.*)(\d*) (.*)(\d+) (.*?)(\d*) (.*?)(\d+) (.*)(\d+)$ (.*?)(\d+)$ (.*)\b(\d+)$ (.*\D)(\d+)$ }; for $pat (@pats) { printf "%-12s ", $pat; if (/$pat/) { print "<$1> <$2>\n"; } else { print "FAIL\n"; } } В результате будет выдано:
(.*)(\d*) <> (.*)(\d+) <7> (.*?)(\d*) <> <> (.*?)(\d+) <2> (.*)(\d+)$ <7> (.*?)(\d+)$ <53147> (.*)\b(\d+)$ <53147> (.*\D)(\d+)$ <53147>

Как видите, все это может быть немого мудрено. Важно понимать, что регулярное выражение - это просто набор утверждений, определяющих успешный результат. Может быть 0, 1 или несколько различных способов удовлетворить определение на конкретной строке. И если имеется несколько вариантов успешного сопоставления, необходимо понимать принципы поиска с возвратом, чтобы понять, какой вариант успешного сопоставления будет получен.

При использовании просмотров вперед и отрицаний, ситуация может еще более усложниться. Предположим, необходимо найти последовательность символов, отличных от цифр, за которыми не идет "123 ". Можно попытаться записать это следующим образом

$_ = "ABC123"; if (/^\D*(?!123)/) { # Ошибка! print "Yup, no 123 in $_\n"; }

Но результата не будет; по крайней мере, такого, как вы ожидали. Утверждается, что в строке нет 123 . Вот более четкая картина того, почему, вопреки популярным ожиданиям, произошло сопоставление:

$x = "ABC123" ; $y = "ABC445" ; print "1: got $1\n" if $x =~ /^(ABC)(?!123)/ ; print "2: got $1\n" if $y =~ /^(ABC)(?!123)/ ; print "3: got $1\n" if $x =~ /^(\D*)(?!123)/ ; print "4: got $1\n" if $y =~ /^(\D*)(?!123)/ ;

Будет выдано

2: got ABC 3: got AB 4: got ABC

Вы могли ожидать, что проверка 3 не сработает, поскольку она кажется более универсальной версией 1. Важное различие между ними состоит в том, что проверка 3 содержит квантификатор (\D*) и поэтому может использовать поиск с возвратом, тогда как проверка 1 - нет. На самом деле вы спрашиваете: "Правда ли, что в начале $x , после 0 или более не цифр, идет нечто, отличающееся от 123 ?". Если механизм сопоставления позволит \D* расшириться до "ABC ", весь шаблон в целом не сопоставится. Поисковая машина первоначально сопоставит \D* с "ABC ". Затем она попытается сопоставить (?!123) c "123 ", что, конечно, невозможно. Но поскольку в регулярном выражении использован квантификатор (\D*) , поисковая машина может вернуться и поискать другое сопоставление в надежде найти сопоставить все регулярное выражение в целом.

Теперь, поскольку сопоставление шаблона так желанно для поисковой машины, она использует стандартный возврат и повторную попытку regexp (backoff-and-retry) и позволяет на это раз \D* расшириться только до "AB ". Теперь и в самом деле имеется нечто после "AB ", что не совпадает с "123 ". Это "C123 ", что вполне устраивает.

Справиться с эти можно, используя совместно утверждение и отрицание. Мы скажем, что после первой части в $1 должна идти цифра, но там должно идти нечто, отличное от "123 ". Помните, что просмотры вперед - это выражения нулевой длины -- при сопоставлении выполняется только проверка, но не берется часть строки. После таких изменений будет получен желаемый результат; т.е. в случае 5 - неудача, а в случае 6 - успех:

Print "5: got $1\n" if $x =~ /^(\D*)(?=\d)(?!123)/ ; print "6: got $1\n" if $y =~ /^(\D*)(?=\d)(?!123)/ ; 6: got ABC

Другими словами, два утверждения нулевой длины (zero-width assertions), идущие подряд, работают так, как если бы проверялась их конъюнкция, так же, как и при использовании любых встроенных утверждений: шаблон /^$/ сопоставляется, только если вы находитесь в начале строки И в конце строки одновременно. Более глубокое основание этого - в том, что соседство в регулярных выражениях всегда означает И, кроме явного указания ИЛИ с помощью вертикальной черты. /ab/ означает сопоставить "a " И (затем) сопоставить "b ", хотя попытки сопоставления и делаются в разных позициях, т.к. "a " - утверждение не нулевой длины, но длины один.

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

/((a{0,5}){0,5}){0,5}/

А если использовать * вместо ограничения количества вхождений от 0 до 5, сопоставление будет выполняться бесконечно -- или пока не исчерпается место в стеке.

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

Если вам не знакомы "стандартные" функции библиотеки regexp версии 8, вот правила сопоставления с образцом, не описанные выше.

Любой одиночный символ сопоставляется с сами собой, если только это не метасимвол, имеющий специальное значение, описанное здесь или выше. Символы, обычно работающие как метасимволы, можно потребовать интерпретировать литерально, предваряя их символом "\ " (например, "\. " соответствует ". ", а не любому символу; "\\ " соответствует "\ "). Последовательность символов сопоставляется с такой же последовательностью символов в целевой строке, поэтому шаблон blurfl сопоставится с "blurfl " в целевой строке.

Можно задать класс символов, включив список символов в квадратные скобки , которые будут сопоставляться с любым из символов в списке. Если первый символ после "[ " - "^ ", класс сопоставляется с любым символом, не указанным в списке. В списке символ "- " используется для указания диапазона, так что a-z представляет все символы от "a " до "z ", включительно.

Символы можно задавать с использованием синтаксиса метасимволов, во многом аналогичного используемому в C: "\n " соответствует переводу строки, "\t " - табуляции, "\r " - возврату каретки, "\f " - form feed и т.д. В общем случае, \nnn , где nnn - это строка восьмеричных цифр, соответствует символу, значение кода ASCII для которого - nnn . Аналогично, \xnn , где nn - это шестнадцатеричные цифры, соответствует символу, значение кода ASCII для которого - nn . Выражение \cx соответствует символу ASCII control-x . Наконец, метасимвол ". " соответствует любому символу, кроме "\n " (если только не используется /s ).

Можно задавать набор альтернатив для шаблона, разделяя их метасимволом "| ", так что fee|fie|foe сопоставится с любой из подстрок "fee ", "fie " или "foe " в целевой строке (так же, как и f(e|i|o)e ). Учтите, что первая альтернатива включает все от последнего разделителя шаблона ("(", "[ " или от начала шаблона) до первого символа "| ", а последняя альтернатива включает все от последнего символа "| " до следующего разделителя шаблона. Поэтому альтернативы обычно берут в круглые скобки, чтобы не сомневаться, где они начинаются и заканчиваются. Учтите, однако, что в квадратных скобках "| " интерпретируется как литерал, поэтому если вы напишите , сопоставление произойдет только с .

В шаблоне можно выделять подшаблоны (путем взятия их в круглые скобки) для дальнейших ссылок и можно ссылаться обратно на n -й подшаблон в дальнейшем с помощью метасимвола \n . Подшаблоны нумеруются слева направо по открывающим круглым скобкам. Учтите, что обратная ссылка сопоставляется с тем, с чем сопоставился подшаблон в рассматриваемой строке, а не с правилами, задающими этот подшаблон. Поэтому (0|0x)\d*\s\1\d* сопоставится с "0x1234 0x4321 ", но не с "0x1234 01234 ", поскольку подшаблон 1 фактически сопоставился с "0x ", хотя правило 0|0x потенциально могло сопоставиться с начальным 0 во втором числе.

ПРЕДУПРЕЖДЕНИЕ о \1 и $1

Некоторые люди слишком привыкли писать вещи типа

$pattern =~ s/(\W)/\\\1/g;

Корни такой привычки восходят к правой части оператора замены в sed , но это плохая привычка. Дело в том, что с точки зрения Perl правая часть s/// - это строка в двойных кавычках. \1 в обычной строке в двойных кавычках означает control-A . Обычное для Unix значение \1 сохранено в s/// . Однако, если вы привыкните делать именно так, у вас будут проблемы при добавлении модификатора /e .

S/(\d+)/ \1 + 1 /eg; или если вы попытаетесь выполнить s/(\d+)/\1000/;

Этой двусмысленности нельзя избежать, написав \{1}000 , но можно, если написать ${1}000 . Просто операцию интерполяции не надо путать с операцией сопоставления с обратной ссылкой. Конечно, они имеют разное значение в левой части оператора s/// .

Секреты регулярных выражений (regular expressions)

Часть 2. Регулярные выражения в конкретных программах

Серия контента:

1. Введение. Знание особенностей повышает эффективность

В предыдущей статье я приводил в основном примеры регулярных выражений без привязки к конкретной программе или языковой среде. Но каждая реализация механизма регулярных выражений имеет свои особенности, свои преимущества, которыми можно воспользоваться, свои недостатки, о которых следует знать, чтобы обходить их. Ведь регулярные выражения не существуют сами по себе, их применение неразрывно связано либо с некоторой утилитой (grep, sed, awk), либо с одним из языков программирования (Perl, Python, Tcl и т.д.).

Зная тонкости реализации механизма регулярных выражений в той или иной программной среде, можно существенно повысить эффективность их практического использования. Здесь я не рассматриваю регулярные выражения для утилит поиска grep/egrep/fgrep, потому что большинство примеров из первой статьи было ориентировано именно на эти программы.

2. Примеры использования регулярных выражений в Perl

Perl является "неофициальным чемпионом" по частоте использования в нём регулярных выражений для решения различных задач среди всех интерпретируемых или скриптовых языков. Несмотря на постоянно растущее скептическое отношение к Perl, он вполне справляется с той работой, для которой главным образом и предназначен – для обработки текстовых данных (вспомним один из вариантов "расшифровки" имени Perl – Practical Extraction and Report Language).

2.1. Корректная версия шаблона для поиска IP-адреса

Впрочем, пора уже перейти к обещанным примерам. Внимательный читатель при изучении примера для поиска IP-адресов из предыдущей статьи наверняка заметил самый большой его недостаток – наряду с корректными IP-адресами регулярное выражение

\{0,2\}\.\{1,3\}\.\{1,3\}\.\{1,3\}

будет находить и выводить строки вида "900.800.700.600", никоим образом к IP-адресам не относящиеся. Диалект простых регулярных выражений в данном случае не позволяет без непомерных затрат времени и сил решить эту проблему. Но в Perl реализованы расширенные регулярные выражения, что позволяет упростить решение.

В первой части IP-адреса может находиться трёхзначное число, начинающееся либо с "1" (за которой могут следовать две любые цифры), либо с "2" (но в этом случае число не должно быть больше 255), или любое двузначное число, или однозначное число (цифры от 1 до 9). На диалекте расширенных регулярных выражений для Perl это можно записать следующим образом:

(||1|2|25)

Обратите внимание на использование новой конструкции группирования символов, которую часто называют дизъюнкцией: a|b|c – т.е. должен совпасть только один из указанных вариантов, – либо a, либо b, либо c. В нашем примере таких взаимоисключающих вариантов пять:

  • – соответствует значениям от 1 до 9;
  • – соответствует значениям от 10 до 99;
  • 1 – соответствует значениям от 100 до 199;
  • 2 – соответствует значениям от 200 до 249;
  • 25 – соответствует значениям от 250 до 255.

Одиночный нуль здесь исключается, так как обычные IP-адреса не содержат значение 0 в первом байте. Это выражение можно немного улучшить, если заменить диапазон применяемым в Perl метасимволом \d (обозначение цифрового символа). После замены выражение приобретёт вид:

(|\d|1\d\d|2\d|25)

Немного короче, но ведь это шаблон только для самой первой части IP-адреса. Во второй и третьей частях допускаются нулевые значения (например, 10.0.0.1), поэтому для них шаблон нужно чуть-чуть изменить:

(|\d|1\d\d|2\d|25)

Шаблон четвёртого байта зависит от контекста поиска. Если вам нужны только IP-адреса хостов, то совпадение с одиночным символом "0" должно быть исключено, и шаблон будет таким же, как для самого первого байта. Если требуются ещё и адреса сетей (подсетей), то можно воспользоваться шаблоном для второго и третьего байтов адреса.

Осталось придать нашему шаблону поиска завершённый вид, который в Perl-скрипте может быть, например, таким:

#!/usr/bin/perl -w open(IN, "./filename.txt"); while() { $ip_addr = ; chomp($ip_addr); if($ip_addr =~ /\/|\d|1\d\d|2\d|25\/\. \/|\d|1\d\d|2\d|25\/\. \/|\d|1\d\d|2\d|25\/\. \/|\d|1\d\d|2\d|25\//) { print "Найден IP-адрес в строке:\n $ip_addr\n"; } } close(IN);

Замечание . В Perl и шаблон регулярного выражения, и варианты в конструкции дизъюнкции записываются между парными символами "слэш" (/). Из-за этого слэши, ограничивающие варианты дизъюнкции, требуют предваряющих экранирующих символов "обратный слэш" (\). Конечно, подобная запись шаблона выглядит жутковато, но зато работает правильно.

2.2. Работа с данными, разделёнными запятыми

Многие системы управления базами данных и электронные таблицы поддерживают вывод в виде списков полей, разделённых запятыми, в качестве стандартного формата обмена данными. Этот формат обозначается аббревиатурой CSV (Comma-Separated Values – значения, разделённые запятой). На первый взгляд, решение задачи распределения таких данных по переменным с помощью Perl выглядит достаточно простым: использовать функцию split /,/ из набора штатных средств. Но внутри полей данных могут содержаться собственные запятые (в символьных строках или в числовых значениях денежных сумм в российских рублях). Что получится в результате обработки функцией split /,/ такой, например, строки данных: "Иванов", "инженер, расчётчик-математик", "4356,50 руб." ?

Чтобы обойти все эти "подводные камни", можно написать специализированную процедуру:

sub csv_parse { my $str_txt = shift; # присваивается первый элемент массива @_ my @fields = (); # массив для сохранения выделенных полей # Запись в цикле в массив значения переменной $+ - фрагмента строки, # для которого обнаружено соответствие шаблону в процессе самой # последней операции поиска (последняя обработанная пара круглых # скобок внутри тела шаблона поиска) push(@fields, $+) while $str_txt =~ m{ "([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx; # Если самый последний символ в исходной строке - запятая, # то список полей завершается "неопределённым значением" undef push(@fields, undef) if substr($str_txt, -1, 1) eq ","; # вернуть список значений, размещённых в отдельных полях return @fields; }

В приведённой выше процедуре первая часть шаблона позволяет выделить фрагмент исходной строки, заключённый в кавычки и ограниченный первой запятой, найденной вне этой пары кавычек. Внутри кавычек могут встречаться любые символы, в том числе и запятые. Вторая часть шаблона соответствует фрагменту без кавычек до первой следующей за ним запятой. Такой фрагмент тоже сохраняется в массиве fields. Последняя часть шаблона – запятая – завершает очередную итерацию цикла. Ключ g после шаблона означает его глобальное действие, т.е. запись в массив всех найденных фрагментов, а не только первого совпадающего. Ключ x позволяет игнорировать все "пробельные символы" в шаблоне (имеются в виду литеральные пробелы, а не метасимволы \s и escape-последовательности). Это немного облегчает чтение шаблона – можно вставить пробелы между символами дизъюнкции (вертикальная черта – разделитель вариантов).

2.3. Небольшие примеры использования Perl для поиска в тексте из командной строки

Нередко встречаются задачи поиска образцов, в условиях которых определено, что надо найти "образец1 И образец2 И образец3". Средства из группы grep легко справляются с задачами поиска одного из вариантов шаблона (образец1|образец2|образец3), но для предложенной задачи потребуется конвейер или другие ухищрения. С помощью Perl подобные задачи решаются "в одно действие":

perl -ne "print if /рубль/ && /доллар/ && /евро/" список_файлов

Здесь ключ e позволяет определить строку выполняемых команд, а ключ n заставляет интерпретатор Perl считать, что заданная последовательность команд заключена в цикл while(<>), т.е. будет выполняться для всех строк перечисленных файлов.

В тех случаях, когда нужно найти абзацы, в которых встречаются все три указанных слова, поможет режим работы с абзацами. Для Perl этот режим активизируется ключом -00:

perl -n00e "print "$_\n" if /рубль/ && /доллар/ && /евро/" список_файлов

А если необходимо вывести список файлов, которые содержат все три слова, то для ключа -0 надо установить такой разделитель записей, который не содержится в обычных текстовых файлах, например, NUL-символ:

perl -ln0e "print $ARGV if /рубль/ && /доллар/ && /евро/" список_файлов

В общем, не спешите "хоронить" Perl – он ещё способен на многое, особенно там, где требуется интенсивная работа с регулярными выражениями.

3. Примеры использования регулярных выражений в Python

Диалект регулярных выражений языка Python довольно-таки близок к диалекту текстового редактора Emacs. Тем не менее в Python синтаксис записи регулярных выражений можно динамически корректировать в любой момент времени. Если вы устали от огромного количества обратных слэшей (те, кто пользовался регулярными выражениями в Emacs, сразу поймёт, что я имею в виду), то можете от них избавиться:

re.set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR)

Первый устанавливаемый флаг говорит о том, что для группирования в шаблонах должны использоваться неэкранированные скобки, а второй флаг – о том, что в конструкции дизъюнкции (выбора варианта) – неэкранированная вертикальная черта. Скорректированные таким образом конструкции будут читаться гораздо легче.

В Python механизм регулярных выражений подключается с помощью модуля re. Поскольку Python по своей сущности является объектно-ориентированным языком, то это в полной мере относится и к его диалекту регулярных выражений. При необходимости создаётся объект типа "регулярное выражение", который в дальнейшем вы можете применять к строкам для выполнения поиска или замены. Рассмотрим следующий фрагмент кода:

undsc_regex = re.compile("\s+(_.+_)\s+") ... result_text = undsc_regex.sub("\\1", input_text)

В первой строке фрагмента создаётся объект-шаблон, соответствующий любой последовательности символов в тексте, начинающейся и заканчивающейся символами подчёркивания (например: "здесь _важно_ отметить"). После создания этот объект можно применять к любым строкам, используя его методы поиска и замены. В данном случае применяется метод замены sub(), который принимает в качестве аргументов строку замены и обрабатываемый текст input_text. Обратите внимание на элемент \1, обозначающий найденный фрагмент и соответствующий той части шаблона, которая заключена в круглые скобки. В отличие от Perl, обозначение \1 включается и в строку замены. В результате обработки текст (сохраняемый в result_text) будет заключён в HTML-тэги "подчёркнутый текст", например: "здесь важно отметить".

А вот как решается проблема с повторяющимися словами-опечатками ("не не", "для для" и т.д.) на языке Python:

#!/usr/bin/python # -*- coding: utf-8 -*- import sys import re # Потребуются три объекта типа "регулярное выражение" RegEx1 = re.compile("\b(\w+)((\s|<[^>]+>)+)(\\1\b)") RegEx2 = re.compile("^([^\033]*\n)+") RegEx3 = re.compile("^(.)") # Обработка всех файлов, имена которых заданы в командной строке for filename in sys.argv: try: fd = sys.open(filename) except: raise "Ошибка при попытке открыть файл" continue # Считать содержимое файла, обработать с помощью трёх подготовленных # регулярных выражений и вывести найденные совпадения txt_data = fd.read() txt_data = RegEx1.gsub("\033 регулярное_выражение строка_поиска [строка_приёмник... ]

Если совпадение с регулярным выражением найдено в строке поиска, то функция возвращает 1, в противном случае – 0. В строку-приёмник (если она задана) копируется совпавший фрагмент. Если заданы имена нескольких строк-приёмников, то им последовательно присваиваются фрагменты, совпавшие с элементами шаблона в круглых скобках, а тем, кому "не хватило" совпадений, присваиваются пустые строки. Если не обнаружено ни одного совпадения с регулярным выражением, то строки-приёмники не изменяются.

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

if 666[А-Я][А-Я]) (.+)} $str_txt {} num owner] { puts "$num $owner" }

В этом примере будут найдены все владельцы автомобилей с "числом зверя" в номере вне зависимости от регистра букв, которыми записан номерной знак (ключ -nocase). Весь совпавший фрагмент не будет сохранён, так как на первом месте в списке строк-приёмников стоит пара фигурных скобок {}, а не имя переменной. Первый фрагмент в скобках (номерной знак) запоминается в переменной num, второй фрагмент в скобках (фамилия владельца) – в переменной owner. Затем значения этих переменных выводятся.

Функция regsub работает аналогично функции regexp:

regsub [ключи] регулярное_выражение строка_поиска строка_замены строка_приёмник

Отличие состоит лишь в том, что после строки поиска записывается строка замены, а строка-приёмник может быть задана только одна.

5. Примеры использования регулярных выражений в sed

Потоковый редактор sed используется главным образом для выполнения массовых замен в текстовых файлах, обрабатываемых построчно. Всем, кто хотя бы немного знаком с sed, известна классическая команда удаления всех пустых строк в обрабатываемом файле:

sed "/^$/d" filename

Эту операцию можно усовершенствовать таким образом, чтобы удалялись не только пустые строки, но и строки, содержащие только символы пробелов и табуляций:

sed "/^[ TAB]*$/d" filename

Здесь под обозначением TAB подразумевается "настоящий", литеральный символ табуляции (генерируемый при нажатии клавиши Tab на клавиатуре).

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

sed " */ /g" filename

Ключ g в конце регулярного выражения сообщает о необходимости выполнения команды глобально, т.е. для всех найденных совпадений, поскольку по умолчанию sed ограничивается только первым найденным совпадением.

Если же, напротив, в начале каждой не пустой строки требуется вставка, например, пары пробелов, то можно воспользоваться функцией логического отрицания:

sed "/^$/!s/^/ /g" filename

6. Заключение

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

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

Ресурсы для скачивания

static.content.url=http://www.сайт/developerworks/js/artrating/

ArticleID=494958

ArticleTitle=Секреты регулярных выражений (regular expressions): Часть 2. Регулярные выражения в конкретных программах



Загрузка...