Пропустить навигацию

Лекция 4. Регулярные выражения

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

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

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

Формально, регулярные выражения - язык для поиска и манипуляции над подстроками в тексте.

Самое простое для чего это можно использовать – на слайдах (поиск символов Ctrl+F).

Вся сила в том что можно задавать очень сложные условия и выбирать конкретные последовательности символов которые вам нужны.

Это только вершина айсберга, того что могут регулярные выражения, это очень обширная тема. Поэтому написано много литературы, много постов и сайтов.

Перед тем как перейдем к систематическому изучению рассмотрим парочку примеров.

/z[aoue]r/

zar, zor, zur, zer

но не zir, dpo, aga

Регулярные выражения обрамляются в слеши. Смотрите на это как на строки - строки обрамляются в кавычки, а регулярные выражения в слеши.

Объяснение простых примеров на слайдах.

И не совсем простой пример – любой адрес электронной почты.

/^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$/

Выглядит довольно пугающе. Синтаксис регулярных выражений создан для текста, он также определен в тексте. В отличие от языков программирования (напиример Javascript) символы, которые здесь используются, не всегда очевидны. Например, в Javascript можно увидеть var и догадаться что это variable – переменная. Этот пример мы разберем чуть позже.

Мы будем использовать простые символы в регулярных выражениях. Но вся сила регулярных выражений – в специальных символах для создания логики.

\

превращает специальный символ в обычный и наоборот

.

любой символ, кроме перевода строки

*

повторение предыдущего символа 0 и более раз

+

повторение предыдущего символа 1 и более раз

?

повторение предыдущего символа 0 или 1 раз

\d

любая цифра

\w

любой словесный символ (буквы, цифры и _)

[XYZ]

любой символ из указанных

[XYZ]+

один или более символов из указанных

$

конец данных

^

начало данных

[^a-z]

НЕ строчная буква (внутри класса ^ означает НЕ)

( )

запоминающие скобки

|

или

{m, n}

от m до n повторений предыдущего символа

В данной таблице показано около одной трети специальных символов. Это основные символы.

Обратный слеш – тоже самое как в  языках программирования, эскейпнуть символ. Например если мы хотим использовать символ кавычки в строке,  то должны поставить \” чтобы Javascript понял что это кавычка. Тоже самое в регулярных выражениях.

Следующий символ это точка – обозначает любую букву или цифру или знак, или дефис, или саму точку.

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

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

Вопросительный знак – опциональный символ – символ который стоит перед знаком вопроса может быть один раз или 0 раз.

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

\w – любой символ буквы цифры или подчеркивание.

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

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

Плюс – и в комбинации – значит любой из этих трех символов может повторяться один и более раз.

Любые данные имеют начало и конец, и знак доллара означает конец данных. Если данные заканчиваются каким то словом – тогда мы поставим это слово, и знак $

Крыша (^) означает начало данных.

Если же мы эту крышу поставим внутри класса (классом мы называем те самые квадратные скобки) то она означает отрицание. Это то, что делается в Javascript и других Си-подобных языках. Пример в таблице означает «не строчная буква», что угодно, но не строчная буква латинского алфавита.

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

| - или -  это очень похоже на две вертикальные черты в яваскрпитпе. В регулярных выражениях это означает - или эта последовательность или другая.

Фигурные скобки для указания конкретного числа повторений. Символ зведочка означает количество повторений от 0 до бесконечности. Если нужно указать конткретное количество раз (например от 4 до 15), то используется запись {4, 15}. Если не указывать второй параметр, то будет до плюс бесконечности, т.е. запись {6, } означает от 6 до плюс бесконечности. Можно сымитировать любые выражения для предыдущих примеров из таблицы – для * это будет {0, }, для + {1,}, для ? {0, 1}, если же не поставить запятую вообще, то это будет означать конкретное количество повторений, т.е. если цифра 6 должна повториться 2 раза то я напишу 6{2},

Чтобы получше изучить на примерах перейдем на сайт regexone.com. В интернете можно найти много обучающих материалов и упражнений. Мы будем использовать regexone.com, это сайт содержит несколько разделов. Первый – интерактивный электронный учебник, который содержит 15 простых упражнений для освоения логики регулярных выражений. И их я предлагаю вам пройти.

Вы можете самостоятельно пройти дома остальные.

Нас ждут 16 упражнений (Выполнение 16 упражнений с объяснением).

  1. Нам предлагается текст, в данном случае три строки. и слева написано нужно или не нужно выбрать эти строки. 1 нужно выбрать все эти три строки. самое простое – нужно найти и понять. что же их все объединяет.  они все начинаются с abc. я напишу абв и получу галочки, что означает что упражнение выполнено.
  2. Во втором примере нужно выбрать три строки. Можно : 123, или сказать любые цифры, т.е. \d или \d\d\d\   \d{3}   \d{0,}   [0-9]{3}    [1-3]{3}
  3. Если просто « . » то выберется любой символ. Помните про экранирующий символ. нужно поставить \. и это выберет текстовую строчку. Не очень хорошо видно, но упражнение выполнено.
  4. Тут помогут квадратные скобки. [cmf]an   
  5. Следующее – можно тоже самое [hf]og или обратной логикой [^b]log. отрицание работает только внутри квадратных скобок (класса данных ).
  6. Первые три начинаются с заглавной буквы. [ABC]  [A-C] [A-Z] [A-Z]..   [H-Z]
  7. Посвящено повторениям. wa ..  z повторяться больше чем 1 раз z{2,4}  z{2,3}  wazz wazz* waz* wazz+
  8. Разное количество разных букв  a*b*c*     aa{2,}b*c*   a*b{0,4}c*
  9. Все они заканчиваются на вопросит знак  .?   суть выбрать вопросит знак \?
  10. Три строки с разного количества пробелов. и пропустить строку начин с символа. \s*   \s+  \s+abc
  11. выбрать первую строчку но не выбирать вторую. ^[^LN]     successful    successful$  \ssuccessful$  :.successful$
  12. Работа с файлами. на вывод пустить только название файла, но опустить расширение. .pdf  .pdf$   нужно название файла но не выводить pdf тут есть несколько способов. (file.*)\.pdf$   файл, любое количество символов, потом точка потом пдф. но то что нужно для вывода – то что находится в скобках.   если например юзер загружает файл на свой сайт
  13. Вложенные запоминающие скобки .  (\w+\s\d+) мы выбрали, но вывели отдельно год. .  (\w+\s(\d+))     (\w+\s(\d{4}))
  14. Разрешения могут содержать разное количество цифр, это полезно если пользователь вводит в таком формате, а вам нужно перевести в массив. (\d+)x(\d+)
  15. I love (cats|dogs).       . I love [cats|dogs].     
  16. .*

Регулярные выражения – очень обширная тема и мы буквально галопом проходим по ней.

в Javascript есть конструктор RegExp.new RegExp(“\\w+c”).

Синтаксис:

new RegExp("pattern"[, флаги])
/pattern/флаги 
var reg = new RegExp("ab+c", "i")
var reg = /ab+c/i

флаги:

“i” – игнорировать регистр символов

“g” – глобальный поиск

“m” – многострочный поиск

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

Объект

Метод

Описание

Возвращает

RegExp

test

Есть ли совпадение в строке

true / false

RegExp

exec

Поиск совпадений в строке

массив

String

search

Поиск совпадений в строке

индекс совпадения / -1

String

match

Поиск совпадений в строке

массив / null

String

replace

Поиск совпадений и замена

строка

String

split

Разбиение строки на массив

подстрок

массив

Первый метод test – проверяет, есть ли совпадение в переданной строке, и возвращает ответ в виде логической переменной да или нет.

метод exec производит поиск совпадений в строке и возвращает массив с данными. Позже мы увидим что это значит.

Остальные методы это методы объекта String.  метод search производит поиск совпадений и возвращает индекс, т.е. то место, где это совпадение найдено или «-1» если совпадение не найдено вообще.

Метод match делает тоже самое, но возвращает массив с данными. В этом массиве будет и индекс, и сама найденная строка, и вся строка в которой происходило все это. Если же ничего не найдено, то он вернет null.

Метод replace находит совпадения и заменяет их на что-то.  Возвращает эту найденную замененную строку.  Если совпадений не найдено, то он вернет ту же строку.

Метод split разбивает строки на массив подстрок, и этот массив возвращает.

Примеры.

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

var reg = /^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$/

Графический онлайн визуализатор выражений - http://www.regexper.com

Метод setTimeout

Синтаксис:

var timerId = setTimeout(func/code, delay[, arg1, arg2...])

Параметры:

func/code

Функция или строка кода для исполнения.

Строка поддерживается для совместимости, использовать её не рекомендуется.

Delay – Задержка в милисекундах, 1000 милисекунд равны 1 секунде.

arg1, arg2… - аргументы, которые нужно передать функции. Не поддерживаются в браузерах IE ниже 9 версии.

Исполнение функции произойдёт спустя время, указанное в параметре delay.

Например, следующий код вызовет alert('Привет') через одну секунду:

function func() {
  alert('Привет');
}
setTimeout(func, 1000);

Если первый аргумент является строкой, то интерпретатор создаёт анонимную функцию из этой строки.

То есть такая запись работает точно так же:

setTimeout("alert('Привет')", 1000)

Метод setInterval

Метод setInterval имеет синтаксис, аналогичный setTimeout.

var timerId = setInterval(func/code, delay[, arg1, arg2...])

Следующий пример при запуске станет выводить сообщение каждые две секунды, пока вы не нажмете на кнопку «Стоп»:Смысл аргументов — тот же самый. Но, в отличие от setTimeout, он запускает выполнение функции не один раз, а регулярно повторяет её через указанный интервал времени. Остановить исполнение можно вызовом clearInterval(timerId).

<input type="button" onclick="clearInterval(timer)" value="Стоп">
<script>
  var i = 1;
  var timer = setInterval(function() { alert(i++) }, 2000);
</script>