regexp

Жизнь заставила окунуться в регулярку, ну что же отправляюсь постигать дзен. Вообще нереально написать неправильное регулярное выражение, можно написать выражение которые будет находить не то что нужно:) Здесь больше рассматривается применение в Unixовом grepе, поэтому перловочники и прочие проходят мимо.
Если у кого есть дельные советы то прошу делиться.

Пару ключей grep :
-v отобразить то, что НЕ совпало с выражением(инверсия)
-o отобразить непосредственный результат, а не всю строку где есть совпадение
-i не учитывать регистр
-с отображает количество совпадений
-E расширенная версия grep
-P perloвая версия (PCRE- Perl-Compatible Regular Expressions)
-n номер строки где есть совпадение
-w только если выражение является словом(пробелы с двух сторон)
-x только если выражение полностью совпадает со строкой!(не совпадет, если в строке есть что-то еще кроме выражения)
-F быстрый grep, ищет только строки, никаких регулярок

При использовании grep обязательно регулярку писать в ‘ ‘ (одинарных кавычках), так вы сбережете нервы на отладке. И не нужно будет экранировать многие символы, будут нормально восприниматься пробелы!!
Используя «» двойные кавычки мы так же можем использовать переменные окружения.
Пример:

Устанавливаем значение переменной ololo = Hell 
% setenv ololo Hell
Выводим значение переменной
% echo $ololo
Hell
Используем переменную окружения в поиске
% cat test.txt | grep  "$ololo"
Hello! My name Alexey! Please visit my web site http://bos-info.com
Hello

В обычном grep нужно экранировать все метасимволы, в результате будет типа так \[Aa\] иначе скобки будут интерпретированы как обычные символы.

. — один любой символ
^ — начало строки
$ — конец строки
| — или 19|20 будет выбран или 19 или 20
+ — один или несколько символов или {1,}
* — любое количество совпадений, втч 0
? — 0 или 1 совпадение с шаблоном или можно записать {0,1}
{n} — количество совпадений с шаблоном
{n,m} — n совпадений с шаблоном, но не более m
{n,} — не менее n совпадений с шаблоном
\ — экранирование символа(например, чтобы найти просто точку нужно использовать экранирование)
Поскольку * и ? жадные кванторы и ищут самое длинное вхождение до конца строки!, то есть ленивые квантаторы, которые ищут короткое вхождение первое совпадение.
*? +? {n,}?
\(regexp\)\{1,3\} — действия будут применяться ко всему выражению в скобках
Также можно использовать ссылку назад, для нахождения нескольких совпадающих слов, например:
\(regexp\).*?\1 \1 — и есть ссылка назад

Txt file:
The red dog fetches the green ball.
The green dog fetches the blue ball.
The blue dog fetches the blue ball.
grep -E '(red|green|blue).*\1' filename

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

Пробельные символы
\t — символ табуляции
\n — перевод строки в win (\r\n)
\f — перевод страницы
\v — вертикальная табуляция
\s — [\t\n\r\f\v]
\S — [^\t\n\r\f\v]

\d — цифры [0-9]
\D — НЕ цифры [^0-9]
\w — [A-Za-z0-9_]
\W — [^A-Za-z0-9_]
\< - начало слова \> — конец слова
\b — граница слова
\B — не граница слова

[Aa] -любой из символов в скобках
[A-Z] с помощью — задаем последовательсность символов
[^A-Z] с помощью ^ операция НЕ, будут найдены значения которые не совпали с теми, что в скобках

POSIX использовать обязательно как показано в двойных скобках(не экранировать)
[[:alnum:]] — [A-Za-z0-9]
[[:alpha:]] — [a-zA-Z]
[[:blank:]] — [\t ] табуляция или пробел
[[:cntrl:]] — ASCII коды 0-31 127
[[:digit:]] — [0-9]
[[:graph:]] — любой печатный символ, пробел исключен
[[:lower:]] — [a-z]
[[:print:]] — любой печатный символ, втч пробел
[[:punct:]] — любой символ не входящий в [[:alnum:]] и [[:cntrl:]]
[[:space:]] — [\f\n\r\t\v ]
[[:upper:]] — [A-Z]
[[:xdigit:]] — [A-Fa-f0-9] hex числа

для поиска символа { в egrep нужно его экранировать достаточно интересным способом [{]

Сравнение синтаксиса обычного и расширенного grep
Основной Расширенный
‘\(red\)’ ‘(red)’
‘a\{1,3\}’ ‘a{1,3}’
‘behaviou\?r’ ‘behaviou?r’
‘pattern\+’ ‘pattern+’

Не реализовано в grep, или я не нашел!

.+(?=regexp2) — просмотр вперед! ищет строку, но не включает в вывод regexp2
(?<=regexp1).+ - просмотр назад! ищет строку, но не включает в вывод regexp1 .+(?!regexp2) - отрицательный просмотр вперед! ищет строку которая не соответствует шаблону и не включает в вывод regexp2 (? %grep -o 'C..' test.txt Cat

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

%grep -Eo '^H.{1,4}\>[[:graph:]][[:space:]]' test.txt
Hello!

3. Вытянуть LA из аптайма

%uptime | grep -o 'load.*'
load averages: 0.09, 0.06, 0.07

4. Вытянуть из нетстата маршрут по умолчанию

%netstat -nr | grep default | grep -o '\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}'
172.16.0.1

P.S.
1. IPv4 адрес
$ grep -E ‘\b((25[0-5]|2[0-4][0-9]|[01]?
[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|
[01]?[0-9][0-9]?)\b’ ololo.txt
2. MAC адрес
$ grep -Ei ‘\b[[:xdigit:]]{2}(:[[:xdigit:]]{2}){5}\b’ ololo.txt

Следующие на очереди sed и awk 🙂

Комментарии: