HPUNIX Сайт о ОС и не только!

Постоянные выражения, базы для работы в Linux

11 марта 2009 - unix

#image.jpgНеплохого времени, гости!

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

Начну с того, что существует несколько разновидностей неизменных выражений:

1. Традиционные неизменные выражения (они же главные, базовые и basic regular expressions (BRE))

  • синтаксис данных выражений определен, как устаревший, но все таки до сих пор широко распространен и  употребляется многими утилитами UNIX
  • Главные неизменные выражения содержат внутри себя следующие метасимволы (об их значениях ниже):
    • .
    • [ ]
    • [^ ]
    • ^
    • $
    • *
    • \{ \} — исходный вариант для { } (в расширенных)
    • \( \) — исходный вариант для ( )(в расширенных)
    • \n, где n — номер от Один до 9
  • Особенности использования данных метасимволов:
    • Звёздочка должна следовать после выражения, соответствующего единичному символу. Пример: [xyz]*.
    • Выражение \(блок\)* следует считать неправильным. В некоторых случаях оно соответствует нулю или более повторений строки блок. В других оно соответствует строке блок*.
    • Внутри символьного класса особенные значения символов, в основном, игнорируются. Особые случаи:
    • Чтобы добавить символ ^ в набор, его следует поместить туда не первым.
    • Чтобы добавить символ -в набор, его следует поместить туда первым или последним. Например:
      • шаблон DNS-имени, куда могут входить буквы, числа, минус и точка-разделитель: [-0-9a-zA-Z.];
      • хоть какой символ, не считая минуса и числа: [^-0-9].
    • Чтобы добавить символ [ или ]в набор, его следует поместить туда первым. Например:
      • [][ab] соответствует ], [, a или b.

2. Расширенные неизменные выражения (они же extended regular expressions (ERE))

  • Синтаксис данных выражений аналогичен синтаксису основных выражений, не считая:
    • Отменено внедрение обратной косой черты для метасимволов { } и ( ).
    • Обратная косая черта перед метасимволом отменяет его особенное значение.
    • Отвергнута теоретически нерегулярная конструкция \n.
    • Добавлены метасимволы +, ?, |.

3. Неизменные выражения, совместимые с Perl (они же Perl-compatible regular expressions (PCRE))

  • имеют более богатый и в то же время предсказуемый синтаксис, чем даже POSIX ERE, поэтому часто употребляется приложениями.

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

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

Правила поиска определяются следующими операциями:

Перечисление |

Вертикальная черта (|) разделяет допустимые варианты, можно сказать - логическое Или. Например, «gray|grey» соответствует gray или grey.

Группировка или объединение ( )

Круглые скобки употребляются для определения области деяния и приоритета операторов. Например, «gray|grey» и «gr(a|e)y» являются разными образцами, но они оба обрисовывают неограниченное количество, содержащее gray и grey.

Квантификация {} ? * +

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

{m,n}

общее выражение, повторений может быть от m до n включительно.

{m,}

общее выражение, m и более повторений.

{,n}

общее выражение, наименее n повторений.

{n}

ровно n повторений.

?

Знак вопроса означает 0 или 1 раз, то же самое, что и {0,1}. Например, «colou?r» соответствует и color, и colour.

*

Звёздочка означает 0, Один или хоть какое число раз ({0,}). Например, «g*gle» соответствует ggle, gogle, google и др.

+

Плюс означает хотя бы 1 раз ({1,}). Например, «go+gle» соответствует gogle, google и т. д. (но не ggle).

Определенный синтаксис данных неизменных выражений зависит от реализации. (другими словами в базовых неизменных выражениях знаки { и } - экранируются обратным слешем)

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

IBM Linux Prodigy Commercial (русские субтитры)

Регулярные выражения, базы для работы в Linux
Регулярные выражения, базы для работы в Linux

. соответствует одному хоть какому символу
[что-то] Соответствует хоть какому единичномусимволу из числа заключённых в скобки. При всем этом:Символ «-» интерпретируется фактически только в этом случае, если он расположен непосредственно после открывающей или перед закрывающей скобкой: [abc-] или [-abc]. В противном случае, он обозначает интервал символов.Например, [abc] соответствует «a», «b» или «c». [a-z] соответствует буквам нижнего регистра латинского алфавита. Эти обозначения могут и сочетаться: [abcq-z] соответствует a, b, c, q, r, s, t, u, v, w, x, y, z.Чтобы установить соответствие символам «[» или «]», достаточно, чтобы закрывающая скобка была первым символом после открывающей: [][ab] соответствует «]», «[», «a» или «b».Если значение в квадратных скобах предварено символом ^, то значение выражения соответствует единичному символу из числа тех, которых нет в скобках. Например, [^abc] соответствует хоть какому символу, не считая «a», «b» или «c». [^a-z] соответствует хоть какому символу, не считая символов нижнего регистра в латинском алфавите.
^ Соответствует началу текста (или началу хоть какой строки, если режим построчный).
$ Соответствует концу текста (или концу хоть какой строки, если режим построчный).
\(\) или ( ) Заявляет «отмеченное подвыражение» (сгруппированное выражение), которое может быть использовано позже (см. следующий элемент: \n). «Отмеченное подвыражение» также является «блоком». В отличие от других операторов, этот (в традиционном синтаксисе) просит бэкслеша, в расширенном и Perl символ \ - не нужен.
\n Где n — это цифра от Один до 9; соответствует n-му отмеченному подвыражению (например (abcd)\0, другими словами знаки abcd отмечены нулем). Эта конструкция теоретически нерегулярна, она не была принята в расширенном синтаксисе неизменных выражений.
*
  • Звёздочка после выражения, соответствующего единичному символу, соответствует нулю или более копий этого (предшествующего) выражения. Например, «[xyz]*» соответствует пустой строке, «x», «y», «zx», «zyx», и т. д.
  • \n*, где n — это цифра от Один до 9, соответствует нулю или более вхождений для соответствия n-го отмеченного подвыражения. Например, «\(a.\)c\1*» соответствует «abcab» и «abcaba», но не «abcac».

!!! Выражение, заключённое в «\(» и «\)» и сопровождаемое «*», следует считать неправильным. В некоторых случаях, оно соответствует нулю или более вхождений строки, которая была заключена в скобки.

В других, оно соответствует выражению, заключённому в скобки, беря во внимание символ «*».

\{x,y\} Соответствует последнему (предстоящему) блоку, встречающемуся более x и наименее y раз. Например, «a\{3,5\}» соответствует «aaa», «aaaa» или «aaaaa». В отличие от других операторов, этот (в традиционном синтаксисе) просит бэкслеша.
.* Обозначение хоть какого количества всех символов меж 2-мя частями неизменного выражения.

Метасимволы нам помогают использовать различные соответствия. Но как представить метасимвол обыденным символом, другими словами символ [ (квадратная скобка) значением квадратной скобки? Просто:

  • необходимо предварить (экранировать) метасимвол (. * + \ ? [ ] { } ) обратным слешем. Например \. или \[

Для упрощения задания некоторых наборов символов, их соединили в т.н.классы и категории символов. POSIX стандартизовал объявление некоторых классов и категорий символов, как показано в следующей таблице:

Регулярные выражения, базы для работы в Linux
POSIX класс аналогично обозначение
[:upper:] [A-Z] знаки верхнего регистра
[:lower:] [a-z] знаки нижнего регистра
[:alpha:] [A-Za-z] знаки верхнего и нижнего регистра
[:alnum:] [A-Za-z0-9] числа, знаки верхнего и нижнего регистра
[:digit:] [0-9] числа
[:xdigit:] [0-9A-Fa-f] шестнадцатеричные числа
[:punct:] [.,!?:…] знаки пунктуации
[:blank:] [ \t] пробел и TAB
[:space:] [ \t\n\r\f\v] знаки пропуска
[:cntrl:] знаки управления
[:graph:] [^ \t\n\r\f\v] знаки печати
[:print:] [^\t\n\r\f\v] знаки печати и знаки пропуска

В regex есть такое понятие как:

Жадность regex

Постараюсь описать как можно понятней. Допустим, мы хотим найти все HTML теги в каком-то тексте. Локализовав задачу, мы хотим найти значения заключенные меж < и >, вместе с этими самыми скобками. Но мы знаем, что теги имеют разную длину и самих тегов, как минимум штук 50.

Перечислять их все , заключив в метасимволы [] - задача очень трудоемкая. Но мы знаем, что у нас есть выражение .* (точка звездочка), характеризующее хоть какое число всех символов в строке.

С помощью данного выражения мы попытаемся найти в тексте (<p>Итак, <strong>Как сделать RAID уровня 10/50 на контроллере LSI MegaRAID (актуально и для: Intel SRCU42x, Intel SRCS16):</strong><span id="more-2058"></span></p>) все значения меж < и >. В конечном итоге, этому выражению будет соответствовать ВСЯ строка. почему, потому что регекс - Жаден и старается захватить Хоть какое ВСЕ количество символов меж < и >, соответственно вся строка, начиная <p>Итак,... и заканчивая ...</span></p> будет принадлежать данному правилу!

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

  • учесть знаки, не соответствующие хотимому образцу (например: <[^>]*> для перечисленного выше варианта)
  • высвободить от жадности, добавив определении квантификатора, как нежадного:
    • *? - «не жадный» («ленивый») эквивалент *
    • +? - «не жадный» («ленивый») эквивалент +
    • {n,}? - «не жадный» («ленивый») эквивалент {n,}
    • .*? - «не жадный» («ленивый») эквивалент .*

Все вышенаписанное желаю дополнить синтаксисом расширенных неизменных выражений:

Неизменные выражения в POSIX подобны традиционному Unix-синтаксису, но с добавлением некоторых метасимволов:

+

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

?

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

|

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

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

Также было отменено внедрение обратной косой черты: \{…\} становится {…} и \(…\) становится (…).

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

[regex@regexp k-max.name]$ cat text1 Один apple Два pear Три banana [regex@regexp k-max.name]$ grep p text1 Один apple Два pear [regex@regexp k-max.name]$ grep pea text1 Два pear [regex@regexp k-max.name]$ grep "p*" text1 Один apple Два pear Три banana [regex@regexp k-max.name]$ grep "pp*" text1 Один apple Два pear [regex@regexp k-max.name]$ grep "x" text1 [regex@regexp k-max.name]$ grep "x*" text1 Один apple Два pear Три banana [regex@regexp k-max.name]$ cat text1 | grep "l\|n" Один apple Три banana [regex@regexp k-max.name]$ echo -e "find an\n* here" | grep "\*" * here [regex@regexp k-max.name]$ grep "pp\+" text1 # строки, с содержанием одной р и Один и более р Один apple [regex@regexp k-max.name]$ grep "pl\?e" text1 Один apple Два pear [regex@regexp k-max.name]$ grep "pl\?e" text1 # pe с возможным символом l Один apple Два pear [regex@regexp k-max.name]$ grep "p.*r" text1 # p, в строках где есть r Два pear [regex@regexp k-max.name]$ grep "a.." text1 # строки с a, за которой следует как минимум Два знака Один apple Три banana [regex@regexp k-max.name]$ grep "\(an\)\+" text1 # Поиск более повторения an Три banana [regex@regexp k-max.name]$ grep "an\(an\)\+" text1 # поиск 2х повторений an Три banana [regex@regexp k-max.name]$ grep "[3p]" text1 # поиск строк, где есть Три или p Один apple Два pear Три banana [regex@regexp k-max.name]$ echo -e "find an\n* here\nsomewhere." | grep "[.*]" * here somewhere. [regex@regexp k-max.name]$ # Ищет знаки от Три до Семь [regex@regexp k-max.name]$ echo -e "123\n456\n789\n0" | grep "[3-7]" 100 20 три 456 Семьсот восемьдесят девять [regex@regexp k-max.name]$ # Ищем цифру, за которой до конца строки нет букв n и r [regex@regexp k-max.name]$ grep "[[:digit:]][^nr]*$" text1 Один apple [regex@regexp k-max.name]$ sed -e '/\(a.*a\)\|\(p.*p\)/s/a/A/g' text1 # замена а на А во всех строках, где после а идет а или после р идет р Один Apple Два pear Три bAnAnA [regex@regexp k-max.name]$ sed -e '/^[^lmnXYZ]*$/s/ear/each/g' text1 # замена ear на each в строках не начинающихся на lmnXYZ Один apple Два peach Три banana [regex@regexp k-max.name]$ echo "First. A phrase.

This is a sentence." |\ # замена последнего слова в предложении на LAST WORLD. &amp;amp;gt; sed -e 's/ [^ ]*\./ LAST WORD./g' First. A LAST WORD. This is a LAST WORD.

Похожие статьи

  • Композиции кнопок для работы в интерпретаторе Bash

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

  • Работа DNS-сервера BIND

    Неплохого времени, уважаемые читатели. На данный момент в блоге желаю рассмотреть работу Domain Name System - сервера на Linux. Разбираясь с работой SAMBA попробовал поднять свой реальный контроллер...

  • Переменные Linux

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

  • Настройка cron планировщика в Linux

    В прошлой теме о демоне syslogd и команде logrotate, я упоминал о планировщике Linux - cron. На данный момент в своем блоге я более кропотливо расскажу о работе данного планировщика.cronПланировщик зад...

  • Управление бесом syslogd и журналированием в Linux

    На данный момент на речь пойдет о журналировании в Linux. Функция системного журналирования (т.н. "логи" или логирование) - это основной источник инфы о работе системы и ошибках. Журналирование может осущ...

Теги:
Рейтинг: +3 Голосов: 35 813 просмотров
Комментарии (0)

Нет комментариев. Ваш будет первым!

Найти на сайте: параметры поиска

Windows 7

Среда Windows 7 на первых порах кажется весьма непривычной для многих.

Windows 8

Если резюмировать все выступления Microsoft на конференции Build 2013.

Windows XP

Если Windows не может корректно завершить работу, в большинстве случаев это

Windows Vista

Если к вашему компьютеру подключено сразу несколько мониторов, и вы регулярно...