Макс Ширшин — Регулярные выражения

Post on 14-Dec-2014

1.047 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Чем могут быть полезны регулярные выражения для разработчика интерфейсов? О каких возможностях следует знать больше? Где находятся «подводные камни» и как обойти их в различных реализациях? И, наконец, что делать, если возможностей встроенной реализации регулярных выражений недостаточно?

TRANSCRIPT

Школа Разработки Интерфейсов Яндекса Симферополь, 2013

Руководитель группы разработки интерфейсов Рекламной Сети Яндекса

Макс Ширшин

Регулярные выражения

Вместо предисловия

2

Виды регулярных выражений

• POSIX (BRE, ERE)

• PCRE = Perl-Compatible Regular Expressions

3

Цитата из стандарта языка JavaScript:

«Вид и функциональность регулярных выражений в JavaScript реализованы по подобию подсистемы регулярных выражений в языке программирования Perl 5»

4

JS-синтаксис (очень кратко)

var re = /^foo/;

5

JS-синтаксис (очень кратко)

var re = /^foo/; // boolean re.test('строка');

6

JS-синтаксис (очень кратко)

var re = /^foo/; // boolean re.test('строка'); // null или Array re.exec('строка');

7

Из чего состоят регэкспы

8

Из чего состоят регэкспы

1. Символы

9

Из чего состоят регэкспы

1. Символы

2. Операции

10

Из чего состоят регэкспы

1. Символы

— обычные

2. Операции

11

Из чего состоят регэкспы

1. Символы

— обычные

— специальные (метасимволы)

2. Операции

12

Из чего состоят регэкспы

1. Символы

— обычные

— специальные (метасимволы)

2. Операции

— квантификация

13

Из чего состоят регэкспы

1. Символы

— обычные

— специальные (метасимволы)

2. Операции

— квантификация

— перечисление

14

Из чего состоят регэкспы

1. Символы

— обычные

— специальные (метасимволы)

2. Операции

— квантификация

— перечисление

— группировка

Метасимволы

8

/./.test('foo'); // true /./.test('\r\n') // false

16

Любой символ

/./.test('foo'); // true /./.test('\r\n') // false Что вы хотели на самом деле: /[\s\S]/ для JS или /./s (не работает в JS)

17

Любой символ

>>> /^something$/.test('something') true

18

Границы строк

>>> /^something$/.test('something') true >>> /^something$/.test('something\nbad') false

19

Границы строк

>>> /^something$/.test('something') true >>> /^something$/.test('something\nbad') false >>> /^something$/m.test('something\nbad') true

20

Границы строк

>>> /\ba/.test('alabama) true

21

Граница слова

>>> /\ba/.test('alabama) true >>> /a\b/.test('alabama') true

22

Граница слова

>>> /\ba/.test('alabama) true >>> /a\b/.test('alabama') true >>> /a\b/.test('naïve') true

23

Граница слова

>>> /\ba/.test('alabama) true >>> /a\b/.test('alabama') true >>> /a\b/.test('naïve') true не-граница слова /\Ba/.test('alabama');

24

Граница слова

Символьные классы

12

/\s/ (инвертированный вариант /\S/)

26

Пробельные символы

/\s/ (инвертированный вариант /\S/) FF: \t \n \v \f \r \u0020 \u00a0 \u1680 \u180e \u2000 \u2001 \u2002 \u2003 \u2004 \u2005 \u2006 \u2007 \u2008 \u2009 \u200a\ u2028 \u2029\ u202f \u205f \u3000 Chrome 19, IE 9: как в FF 12 и ещё \ufeff IE 7, 8 :-( только: \t \n \v \f \r \u0020

27

Пробельные символы

/\d/ ~ цифры от 0 до 9 /\w/ ~ буквы, цифры и подчёркивание В JS не работает для русских букв! И наоборот: /\D/ ~ всё, кроме цифр /\W/ ~ всё, кроме букв и цифр

28

Буквы и цифры

Пример: /[abc123]/

29

Произвольные классы символов

Пример: /[abc123]/ Работают метасимволы и диапазоны: /[A-F\d]/

30

Произвольные классы символов

Пример: /[abc123]/ Работают метасимволы и диапазоны: /[A-F\d]/ Можно указать несколько диапазонов: /[a-cG-M0-7]/

31

Произвольные классы символов

Пример: /[abc123]/ Работают метасимволы и диапазоны: /[A-F\d]/ Можно указать несколько диапазонов: /[a-cG-M0-7]/ ВАЖНО: диапазоны берутся из Юникода. При работе с кириллическими диапазонами проверьте порядок символов в Юникоде!

32

Произвольные классы символов

символ «точка» — просто точка! /[.]/.test('anything') // false

33

Произвольные классы символов

символ «точка» — просто точка! /[.]/.test('anything') // false символы: \ ] - /[\\\]-]/

34

Произвольные классы символов

всё, кроме a, b, c: /[^abc]/ ^ как символ: /[abc^]/

35

Инвертированные символьные классы

Квантификаторы

18

/bo*/.test('b') // true

37

Ноль или более, один или более

/bo*/.test('b') // true /.*/.test('') // true

38

Ноль или более, один или более

/bo*/.test('b') // true /.*/.test('') // true /bo+/.test('b') // false

39

Ноль или более, один или более

/colou?r/.test('color'); /colou?r/.test('colour');

40

Ноль или один

41

Диапазоны повторов

/bo{7}/ точно 7

42

Диапазоны повторов

/bo{7}/ точно 7 /bo{2,5}/ от 2 до 5, x < y

43

Диапазоны повторов

/bo{7}/ точно 7 /bo{2,5}/ от 2 до 5, x < y /bo{5,}/ 5 или более

44

Диапазоны повторов

/bo{7}/ точно 7 /bo{2,5}/ от 2 до 5, x < y /bo{5,}/ 5 или более в JS не работает! /b{,5}/.test('bbbbb')

var r = /a+/.exec('aaaaa');

45

Жадные (greedy) квантификаторы

var r = /a+/.exec('aaaaa'); >>> r[0]

46

Жадные (greedy) квантификаторы

var r = /a+/.exec('aaaaa'); >>> r[0] "aaaaa"

47

Жадные (greedy) квантификаторы

var r = /a+?/.exec('aaaaa');

48

Ленивые (lazy) квантификаторы

var r = /a+?/.exec('aaaaa'); >>> r[0]

49

Ленивые (lazy) квантификаторы

var r = /a+?/.exec('aaaaa'); >>> r[0] "a"

50

Ленивые (lazy) квантификаторы

var r = /a+?/.exec('aaaaa'); >>> r[0] "a" r = /a*?/.exec('aaaaa');

51

Ленивые (lazy) квантификаторы

var r = /a+?/.exec('aaaaa'); >>> r[0] "a" r = /a*?/.exec('aaaaa'); >>> r[0]

52

Ленивые (lazy) квантификаторы

var r = /a+?/.exec('aaaaa'); >>> r[0] "a" r = /a*?/.exec('aaaaa'); >>> r[0] ""

53

Ленивые (lazy) квантификаторы

Группировки

24

с захватом

/(boo)/.test("boo");

55

Группировки

с захватом

/(boo)/.test("boo"); без захвата

/(?:boo)/.test("boo");

56

Группировки

var result = /(bo)o+(b)/.exec('the booooob');

57

Группировки и конструктор RegExp

var result = /(bo)o+(b)/.exec('the booooob'); >>> RegExp.$1 "bo"

58

Группировки и конструктор RegExp

var result = /(bo)o+(b)/.exec('the booooob'); >>> RegExp.$1 "bo" >>> RegExp.$2 "b"

59

Группировки и конструктор RegExp

var result = /(bo)o+(b)/.exec('the booooob'); >>> RegExp.$1 "bo" >>> RegExp.$2 "b" >>> RegExp.$9 ""

60

Группировки и конструктор RegExp

var result = /(bo)o+(b)/.exec('the booooob'); >>> RegExp.$1 "bo" >>> RegExp.$2 "b" >>> RegExp.$9 "" >>> RegExp.$10 undefined

61

Группировки и конструктор RegExp

var result = /(bo)o+(b)/.exec('the booooob'); >>> RegExp.$1 "bo" >>> RegExp.$2 "b" >>> RegExp.$9 "" >>> RegExp.$10 undefined >>> RegExp.$0 undefined

62

Группировки и конструктор RegExp

/((foo) (b(a)r))/

63

Порядок нумерации группировок

/((foo) (b(a)r))/ $1 ( ) foo bar

64

Порядок нумерации группировок

/((foo) (b(a)r))/ $1 ( ) foo bar $2 ( ) foo

65

Порядок нумерации группировок

/((foo) (b(a)r))/ $1 ( ) foo bar $2 ( ) foo $3 ( ) bar

66

Порядок нумерации группировок

/((foo) (b(a)r))/ $1 ( ) foo bar $2 ( ) foo $3 ( ) bar $4 ( ) a

67

Порядок нумерации группировок

var r = /best(?= match)/.exec('best match');

68

Lookahead

var r = /best(?= match)/.exec('best match'); >>> !!r true

69

Lookahead

var r = /best(?= match)/.exec('best match'); >>> !!r true >>> r[0] "best"

70

Lookahead

var r = /best(?= match)/.exec('best match'); >>> !!r true >>> r[0] "best" >>> /best(?! match)/.test('best match') false

71

Lookahead

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

30

/red|green|blue light/ /(red|green|blue) light/ >>> /var a(;|$)/.test('var a') true

73

Логическое «или»

true /(red|green) apple is \1/.test('red apple is red') true /(red|green) apple is \1/.test('green apple is green')

74

Backreferences (обратные ссылки)

Представление символов

32

\x09 === \t (не Unicode, для ASCII/ANSI) \u20AC === € (для Unicode)

76

Представление символов

\x09 === \t (не Unicode, для ASCII/ANSI) \u20AC === € (для Unicode) обратный slash убирает специальное значение у символа /\(\)/.test('()') // true /\\n/.test('\\n') // true

77

Представление символов

\x09 === \t (не Unicode, для ASCII/ANSI) \u20AC === € (для Unicode) обратный slash убирает специальное значение у символа /\(\)/.test('()') // true /\\n/.test('\\n') // true иногда верно и обратное /\f/.test('f') // false!

78

Представление символов

Флаги

34

g i m s x

80

Флаги в регулярных выражениях

g i m s x global match

81

Флаги в регулярных выражениях

g i m s x global match ignore case

82

Флаги в регулярных выражениях

g i m s x global match ignore case multiline matching for ^ and $

83

Флаги в регулярных выражениях

g i m s x global match ignore case multiline matching for ^ and $ нет поддержки в JS для: string as single line extend pattern

84

Флаги в регулярных выражениях

/(?i)foo/ /(?i-m)bar$/ /(?i-sm).x$/ /(?i)foo(?-i)bar/ Не все реализации поддерживают переключение флагов внутри regexp. JS при таком синтаксисе включает флаги на весь regexp сразу и не даёт менять.

85

Альтернативный синтаксис для флагов

RegExp в JavaScript

86

экземпляры RegExp: /regexp/.exec('строка') null или массив ['всё совпадение', $1, $2, ...] /regexp/.test('строка') false или true экземпляры String: 'str'.match(/regexp/) 'str'.match('\\w{1,3}') - эквивалент /regexp/.exec, если нет флага g; - массив всех совпадений по строке, если есть флаг g (внутренние группировки игнорируются) 'str'.search(/regexp/) 'str'.search('\\w{1,3}') позиция первого совпадения или -1

87

Методы

экземпляры String: 'str'.replace(/old/, 'new'); В строке замены поддерживаются следующие спецсимволы: $$ вставляет значок доллара "$" $& подстрока, совпавшая с регэкспом $` подстрока до $& $' подстрока после $& $1, $2, $3 и т.д.: cтрока, совпавшая с соответствующей скобочной группировкой 'str'.replace(/(r)(e)gexp/g, function(matched, $1, $2, offset, sourceString) { // чем заменить matched на этом шаге? return 'замена'; });

88

Методы

// ПЛОХО var re = new RegExp('^' + userInput + '$'); var userInput = '[abc]'; // ХОРОШО RegExp.escape = function(text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }; var re = new RegExp('^' + RegExp.escape(userInput) + '$');

89

RegExp injection

Что почитать

90

91

В интернете: javascript.ru/basic/regular-expression

Mastering Regular Expressions

O'Reilly Media

Книга:

Вопросы?

92

Руководитель группы разработки интерфейсов Рекламной Сети Яндекса

ingdir@yandex-team.ru

@ingdir

Макс Ширшин

top related