Урок 6. Соответствие позицийТеперь вы знаете, как установить соответствие между всеми типами символов во всевозможных типах комбинаций и повторений в любом положении в тексте. Однако иногда необходимо установить соответствие в определенных местоположениях в пределах блока текста, для чего требуется установить соответствие позиций, — именно это объясняется в данном уроке. Использование границСоответствие позиций позволяет указать, где в строке текста должно произойти совпадение. Чтобы понять потребность в соответствии позиций, рассмотрим следующий пример: Текст The cat scattered his food all over the room. Регулярное выражение cat Результат The cat scattered his food all over the room. Шаблон cat (кот) соответствует всем вхождениям cat даже вхождению cat в слово scattered. На самом деле иногда как раз это и нужно, но более чем вероятно, что требуется совсем другое. Если вы хотите в результате поиска заменить все вхождения слова cat на слово dog, то при таком поиске все закончилось бы следующей ерундой: The dog sdogtered his food all over the room. Это заставляет нас учитывать границы и использовать специальные метасимволы для определения позиции (или границы) перед шаблоном и после него. Границы слова
Символ
Чтобы продемонстрировать использование Текст The cat scattered his food all over the room. Регулярное выражение cat Результат The cat scattered his food all over the room.
Перед словом cat и после него есть пробел, и слово вместе с пробелами соответствует шаблону ЗамечаниеТак чему же именно соответствует \b? Механизмы регулярных выражений не понимают английский или любой другой язык, и потому они не могут определить границы слова. Символ \b просто соответствует позиции между символом, который является обычно частью слова (слова состоят из алфавитно-цифровых символов и символа подчеркивания, т.е. представляют собой текст, который состоит из символов, соответствующих \w) и чем-нибудь, что не может быть частью слова (текст, который состоит из символов, соответствующих \w). Важно помнить, что для того, чтобы найти слово целиком, \b должен использоваться и перед, и после текста, с которым будет установлено соответствие. Рассмотрим следующий пример: Текст The captain wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel. Регулярное выражение \bcap Результат The captain wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel. Шаблон \bcap соответствует любому слову, которое на¬чинается с cap, и потому были найдены четыре слова, при¬чем три из них не являются словом cap. Далее приведен тот же самый пример, но только \b стоит в конце слова: Текст The captain wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel. Регулярное выражение cap\b Результат The captain wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel. Выражение сар\b соответствует любому слову, которое заканчивается на cap, и потому были найдены два совпадения, включая и то слово, которое не является словом cap. Но если нужно найти только слово cap, правильным шаблоном является только \bcap\b. ЗамечаниеНа самом деле символ \b не соответствует какому-либо символу; он соответствует позиции. Поэтому длина строки, которая находится шаблоном \bcat\b, равна трем (с, а и t), а не пяти символам. Чтобы указать нечто, не соответствующее границе слова, используйте \B. В следующем примере метасимволы \B помогают определить местонахождение дефисов с лишними пробелами вокруг них: Текст Please enter the nine-digit id as it appears on your color - coded pass-key. Регулярное выражение \B-\B Результат
Please enter the nine-digit id as it appears on your
color - coded pass-key.
\B-\B соответствует дефису, который окружен символами границы слова. Дефисы в nine-digit и pass-key не соответствуют шаблону, но дефис в color - coded будет найден. Как указывалось в уроке 4, "Использование метасимволов", метасимволы на верхнем регистре обычно отрицают функциональные возможности их эквивалентов на нижнем регистре. ЗамечаниеВ некоторых реализациях регулярных выражений поддерживается два дополнительных метасимвола. Метасимвол \b соответствует началу или концу слова, дополнительный метасимвол \< соответствует только началу слова, а дополнительный метасимвол \> соответствует только концу слова. Хотя использование этих символов обеспечивает дополнительное управление, поддержка их очень ограничена. Определение границ строкГраницы слов позволяют указать местонахождение совпадений относительно позиции в слове (начало слова, конец слова, полностью слово и т.д.). Границы строк выполняют подобную функцию, но используются для нахождения соответствий с шаблонами в начале или конце всей строки. Метасимволы для границ строк — крыша ^ (начало строки) и доллар $ (конец строки). Замечание
В уроке 3, "Соответствие набору символов", вы узнали, что крыша ^ используется для того, чтобы отрицать набор. Как же она может использоваться также и для указания начала строки?
Чтобы продемонстрировать использование границ строк, рассмотрим следующий пример. Правильные (допустимые) XML-документы начинаются с Текст <?xml version="1.0" encoding="UTF-8" ?> <wsdl:definitions targetNamespace="http://tips.cf" xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf" xmlns:apachesoap="http://xml.apache.org/xml-soap" Регулярное выражение <\?xml.*\?> Результат
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf"
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
Шаблон, казалось, сработал. Но это очень грубая проверка. Рассмотрим следующий пример: тот же шаблон используется для того, чтобы найти текст, которому предшествует лишний текст перед открытием XML. Текст This is bad, real bad! <?xml version="1.0" encoding="UTF-8" ?> <wsdl:definitions targetNamespace="http://tips.cf" xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf" xmlns:apachesoap="http://xml.apache.org/xml-soap" Регулярное выражение <\?xml.*\?> Результат
This is bad, real bad!
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf"
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
Шаблон Необходимо проверить, что открывающий XML-тег на самом деле является первым текстом в строке, и именно это должен сделать метасимвол ^: Текст <?xml version="1.0" encoding="UTF-8" ?> <wsdl:definitions targetNamespace="http://tips.cf" xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf" xmlns:apachesoap="http://xml.apache.org/xml-soap" Регулярное выражение ^\s<\?xml.*\?> Результат
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf"
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
Первый символ ^ соответствует началу строки, поэтому ^\s* соответствует началу строки, после которого следует нуль или большее количество пробельных символов (таким образом обрабатываются допустимые пробелы, позиции табуляции и концы строк перед открытием XML-документа). Следовательно, весь шаблон Замечание
Шаблон
Знак $ используется во многом аналогичным способом. Этот знак помогает проверить, что после закрывающего тега </[Hh][Tt][Mm][Ll]>\s*$ Наборы используются для каждого из символов H, T, M и L (чтобы обработать любую комбинацию символов верхнего и нижнего регистров), a \s*$ соответствуют любому пробельному символу, за которым следует конец строки. ЗамечаниеШаблон ^.*$ — синтаксически правильное регулярное выражение, которое почти всегда будет находить соответствие, и потому оно совершенно бесполезно. Попробуйте догадаться, чему соответствует данное выражение и когда оно не будет находить соответствие. Использование многострочного режимаОбычно ^ соответствует началу строки, а $ — концу строки. Однако есть исключение, а точнее, способ изменить такое поведение этих символов.
Во многих реализациях регулярных выражений имеются специальные метасимволы, которые изменяют поведение других метасимволов; один из них — (?m). Этот метасимвол допускает использование многострочного режима. Многострочный режим вынуждает механизм регулярных выражений обрабатывать конец строки как разделитель строк, и в этом режиме ^ соответствует началу строки или началу после конца строки (т.е. началу новой строки), а $ соответствует концу строки или концу после конца строки. Метасимвол (?m) (если он, конечно, применяется) должен быть помещен в самое начало шаблона, как показано в следующем примере, в котором регулярное выражение помогает определить местонахождение всех комментариев в блоке кода, написанном на JavaScript: Текст <SCRIPT> function doSpellCheck(fora, field) { // Make sure not empty if (field.value == '') { return false; } // Init var windowName='spellWindow'; var spellCheckURL='spell.cfm?formname=comment&fieldname='+field.name; .......... // Done return false; } </SCRIPT> Регулярное выражение (?m)^\s*//.*$ Результат <SCRIPT> function doSpellCheck(fora, field) { // Make sure not empty if (field.value == '') { return false; } // Init var windowName='spellWindow'; var spellCheckURL='spell.cfm?formname=comment&fieldname='+field.name; .......... // Done return false; } </SCRIPT>
Выражение ЗамечаниеВыражение (?m) не поддерживается многими реализациями регулярных выражений. ЗамечаниеВ некоторых реализациях регулярных выражений также поддерживается метасимвол \A, соответствующий началу строки, и метасимвол \Z, соответствующий концу строки. Если эти метасимволы поддер¬живаются, то ведут себя они очень похоже на ^ и $, но в отличие от ^ и $, они не модифицируются метасимволом {?m) и поэтому не будут работать в многострочном режиме. РезюмеРегулярные выражения могут соответствовать любым блокам текста или тексту в определенной позиции в строке. Символ \b соответствует границе слова (а \B — его противоположность — все делает полностью наоборот). Метасимволы ^ и $ отмечают границы строк {начало строки и конец строки, соответственно), хотя когда используется модификатор (?m), ^ и $ будут также соответствовать строкам, которые начинаются или заканчиваются в конце строки (т.е. там, где стоит символ разрыва строки). |
||