Дозволяють формувати умови для наступних операцій:
проводити текстовий пошук;
перевіряти дані, що вводяться користувачем;
замінювати чи витягувати ділянки тексту;
Розділяти текст на блоки.
"Some people, when confronted with a problem, think "I know, I'll use regular
expressions." Now they have two problems."
-Jamie Zawinski, 1997
В bash регулярні вирази допустимі у складовій команді [[ при використанні порівняння =~, наприклад, в операторі if.
Однак регулярні вирази є важливою частиною ширшого інструментарію для таких команд, як grep, awk і особливо sed.
Це дуже потужні команди, тому їх потрібно знати.
Візьмемо такий приклад тексту.
Пример 3.1. Файл frost.txt
1 Two roads diverged in a yellow wood,
2 And sorry I could not travel both
3 And be one traveler, long I stood
4 And looked down one as far as I could
5 To where it bent in the undergrowth;
7
6 Excerpt from The Road Not Taken by Robert Frost
Команда grep виконує пошук за вмістом файлів за допомогою заданого шаблону та виводить будь-який рядок, який йому відповідає. Щоб використати команду grep, вам потрібно вказати шаблон і одне або кілька імен файлів (Імена файлів можуть бути передані через канал передачі даних).
-c — вивести кількість рядків, які відповідають шаблону;
-E — увімкнути розширений регулярний вираз (без необхідності екранування спеціальних символів);
-f — читати шаблон пошуку, який знаходиться у наданому файлі. Файл може містити кілька шаблонів, причому кожен рядок включає в себе один шаблон;
-i — ігнорувати регістр символів;
-l — вивести лише ім’я файлу та шлях, яким було знайдено шаблон;
-n — вивести номер рядка файлу, в якому було знайдено шаблон;
-P - включити механізм регулярних виразів Perl;
-R , -r - виконати рекурсивний пошук підкаталогів.
Сигнатура дзвінка.
grep параметри шаблон імена_файлів
Для пошуку в каталозі /home та у всіх його підкаталогах файлів, що містять слово password незалежно від регістру, виконайте команду:
grep -R -i 'password' /home
password - це літерал
Літерал це найпростіший шаблон пошуку, при якому шукаємо слово.
Регулярні вирази в мовах, відмінних від BASH, прийнято обрамляти прямими слішами.
Типу такого:
/password/
Якщо простий символ - це просто символ, який ви шукаєте, то метасимвол означає щось більше, а саме певне правило.
Відповідає будь-якому символу, окрім нового рядка.
$ grep 'T.o' frost.txt
1 Two roads diverged in a yellow wood,
Шаблони регулярних виразів також чутливі до регістру, тому рядок 3 файлу не повертається, хоча містить слово too.
Якщо ви хочете трактувати цей метасимвол як символ точки, а не як символ підстановки, додайте перед ним зворотний сліш (.).
У регулярному вираженні знак питання (?) робить будь-який попередній йому символ необов’язковий.
$ egrep 'T.?o' frost.txt
1 Two roads diverged in a yellow wood,
5 To where it bent in the undergrowth;
egrep - без учора регістру (аналогічно grep-E)
У регулярних виразах зірочка ( * ) - це спеціальний символ, (схожий на ?) який відповідає попередньому елементу необмежену кількість разів.
$ grep 'T.*o' frost.txt
1 Two roads diverged in a yellow wood,
5 To where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frost
Метасимвол плюс ( + ) працює так само, як і * , за винятком того, що попередній елемент повинен зустрітися хоча б одного разу.
Іншими словами, він відповідає попередньому елементу, який з’являється один раз або більше:
$ egrep 'T.+o' frost.txt
1 Two roads diverged in a yellow wood,
5 To where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frost
Для групування символів можна використовувати дужки. Крім іншого, це дозволить нам розглядати символи, розташовані всередині дужок, як один елемент, який далі можна посилатися.
Ось приклад угруповання:
$ egrep 'And be one (stranger|traveler), long I stood' frost.txt
3 And be one traveler, long I stood
| - логічне АБО
Квадратні дужки [ ] призначені для визначення класів та списків допустимих символів.
Ними можна вказати, які символи у цій позиції у шаблоні збігаються.
Це особливо корисно при спробі перевірити введення користувача. Для короткості при вказівці діапазону можна додати тире, наприклад [a-j] .
[abc] - Відповідає лише символу a, або b, або c
[1–5] - Відповідає цифрам в діапазоні від 1 до 5
[a–zA–Z] - Відповідає будь-якій малі або великій літері від a до z
[0–9 +–*/] - Відповідає числам або вказаним чотирма математичними символами
[0–9a–fA–F] - Відповідає шістнадцятковому символу
Крім того, є зумовлені символьні класи, відомі як скорочення для набору символів.
\s - Пробельний символ
\S - Непробільний символ
\d - Цифровий символ
\D - Нецифровий символ
\w - Слово
\W - Не слово
\x - Шістнадцяткове число (наприклад, 0x5F)
Наприклад, знайти будь-які числа у файлі frost.txt
$ grep -P '\d' frost.txt
Інші символьні класи (з більш докладним синтаксисом) дійсні тільки всередині дужок
[:alnum:] - Будь-який буквено-цифровий символ
[:alpha:] - Будь-який алфавітний символ
[:cntrl:] - Будь-який керуючий символ
[:digit:] - Будь-яка цифра
[:graph:] - Будь-який графічний символ
[:lower:] - Будь-який символ нижнього регістру
[:print:] - Будь-який друкований символ
[:punct:] - Будь-який розділовий знак
[:space:] - Будь-який символ пробілу
[:upper:] - Будь-який символ верхнього регістру
[:xdigit:] - Будь-яка шістнадцяткова цифра
Приклад:
grep 'X[[:upper:][:digit:]]' idlist.txt
Відповідно до цієї команди буде виконано пошук вмісту у файлі idlist.txt і в результаті буде виведено будь-який рядок, що містить символ X, за яким слід будь-яка велика літера або цифра.
Зворотні посилання на регулярні вирази є одним із найпотужніших і часто збиває з пантелику операцією регулярних виразів. Розглянемо 1 наступний файл tags.txt:
<i>line</i>
is
<div>great</div>
<u>!</u>
Припустимо, ви хочете написати регулярний вираз, який витягуватиме будь-який рядок, що містить пару повних тегів HTML. Ви можете зосередитись на форматі тега HTML та використовувати зворотне посилання на регулярне вираз, як показано нижче:
$ egrep '<([A-Za-z]*)>.*<!--\1-->' tags.txt
<i>line</i>
<div>great</div>
<u>!</u>
У цьому прикладі зворотне посилання \1 розташоване в останній частині регулярного посилання вирази. Це посилання направляє нас до виразу, укладеного в перший набір дужок [A-Za-z]* .
Квантифікатори вказують, скільки разів елемент повинен з’явитися в рядку, і визначаються фігурними дужками {}.
Наприклад, шаблон T{5} означає, що літера T повинна послідовно з’являтися п’ять разів.
** T {3,6} ** - від трьох до шести разів
T{5,} - п’ять разів чи більше.
Якщо потрібно вказати, що шаблон повинен бути на початку або в кінці рядка, використовують якорі.
Символ каретки (^) призначений для прив’язки шаблону до початку рядка. Наприклад, ^[1-5] означає, що відповідний рядок має починатися з однієї із цифр від 1 до 5. Символ $ використовується для прив’язки шаблону до кінця послідовності чи рядка.
Наприклад, [1-5]$ означає, що рядок повинен закінчуватися однією із цифр від 1 до 5.
** Капелюшок (^) може ще позначати логічне заперечення!
$ - кінець рядка
приклад.
^Name:[\sa-zA-Z]+$
Перевірка телефону.
/\d+[-s]?\d+[-s]?\d+/
[-\s] - дефіс або пробіл
Варіанти перевірки email
/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
ˆ[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)* @ [a-zA-Z0-9-]+\.([azA-Z]{2,3})$
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Ось така “жесть” для розуміння цього регулювання!
Перевірка ip адреси
((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}
Імпорт пакету.
import re
Далі ми повинні відкомпілювати регулювання в байт-код, здатний до виконання C.
pattern = re.compile('foo')
Під час компіляції можна вказувати прапори.
pattern = re.compile("^\w+\: (\w+/\w+/\w+)", re.MULTILINE)
re.MULTILINE - компілюватиме для пошуку у всіх рядках, якщо його не вказати, то шукатиме тільки в першому.
Після компіляції нам повертається об’єкт, який підтримує пошук та інші операції.
Пошук збігів.
pattern.match("foo bar")
pattern.search("Hello world")
Ця система поверне об’єкт MatchObject збігу або None.
Дістаємо збіги з MatchObject групами.
match.group()
match.group(0)
match.group(1)
Повертаємо перелік збігів.
list = pattern.findall("hello world")
Тут все набагато простіше.
var email = "joerg@krause.net";
console.log(check(email));
function check(email) {
if (email.match(/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+\\
.([a-zA-Z]{2,3})$/)) {
return true;
} else {
return false;
}
}
Як видно рядки в js-ці вміють приймати регулярку в методі match
Для тих, хто цікавиться, наведу докладний виклад послідовності цієї перевірки.
Ручне створення шаблону та тестування.
var patt = /^auto$/;
console.log(patt.test("auto"));
Другий варіант з exec().
<script>
var re = /^[0-9]{5}$/;
var field = "12683";
var checkzip = re.exec(feld);
if(!checkzip) {
alert("The zip code " + checkplz + " is not correct.");
} else {
console.log(checkplz)
}
</script>
Об’єкт для роботи з регулюванням RegExp
Методи об’єкту
exec() - тестує та повертає перше влучення
test() - тестує та повертає true або false
toString() - повертає вираз як рядок
приклад.
var text = "Than Ann answers all questions again.";
var patt = /a/g;
var match = patt.exec(text);
console.log(match[0] + " found at " + match.index);
match = patt.exec(text);
do {
match = patt.exec(text);
if (!match) break;
console.log(match[0] +" found at " + match.index);
} while(true);
Висновок.
Як бачимо, для того щоб пробігатися по всіх збігах, необхідно “крутити” цикл, де викликати exec() і переривати його коли збіги закінчаться.
if (! match) break;