Выразительный JavaScript: Регулярные выражения Страница 2

Выразительный JavaScript: Регулярные выражения

Метод search

Admin » » Сообщение:

Метод indexOf нельзя использовать с регулярками. Зато есть метод search, который как раз ожидает регулярку. Как и indexOf, он возвращает индекс первого вхождения, или -1, если его не случилось.

Код: Выделить всё Развернуть
console.log("  word".search(/\S/));
// → 2
console.log("    ".search(/\S/));
// → -1

К сожалению, никак нельзя задать, чтобы метод искал совпадение, начиная с конкретного смещения (как это можно сделать с indexOf). Это было бы полезно.

метод, search, indexof, свойство, lastindex, exec, source, match, replace, цикл, вхождение, re.exec, while, разбор, ini файлы, string, split, unicode, символ, регулярка, регулярки, объекты, шаблоны, поиск, строки, синтаксис, выражения, test, index, regexp, инструменты

Свойство lastIndex

Admin » » Сообщение:

Метод exec тоже не дает удобного способа начать поиск с заданной позиции в строке. Но неудобный способ дает.

У объекта регулярок есть свойства. Одно из них - source, содержащее строку. Еще одно - lastIndex, контролирующее, в некоторых условиях, где начнется следующий поиск вхождений.

Эти условия включают необходимость присутствия глобальной опции g, и то, что поиск должен идти с применением метода exec. Более разумным решением было бы просто допустить дополнительный аргумент для передачи в exec, но разумность - не основополагающая черта в интерфейсе регулярок JavaScript.

Код: Выделить всё Развернуть
var pattern = /y/g;
pattern.lastIndex = 3;
var match = pattern.exec("xyzzy");
console.log(match.index);
// → 4
console.log(pattern.lastIndex);
// → 5

Если поиск был успешным, вызов exec обновляет свойство lastIndex, чтоб оно указывало на позицию после найденного вхождения. Если успеха не было, lastIndex устанавливается в ноль - как и lastIndex у только что созданного объекта.

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

Код: Выделить всё Развернуть
var digit = /\d/g;
console.log(digit.exec("here it is: 1"));
// → ["1"]
console.log(digit.exec("and now: 1"));
// → null

Еще один интересный эффект опции g в том, что она меняет работу метода match. Когда он вызывается с этой опцией, вместо возврата массива, похожего на результат работы exec, он находит все вхождения шаблона в строке и возвращает массив из найденных подстрок.

Код: Выделить всё Развернуть
console.log("Банан".match(/ан/g));
// → ["ан", "ан"]

Так что поосторожнее с глобальными переменными-регулярками. В случаях, когда они необходимы - вызовы replace или места, где вы специально используете lastIndex - пожалуй и все случаи, в которых их следует применять.

свойство, lastindex, exec, source, match, replace,

Циклы по вхождениям

Admin » » Сообщение:

Типичная задача – пройти по всем вхождениям шаблона в строку так, чтобы иметь доступ к объекту match в теле цикла, используя lastIndex и exec.

Код: Выделить всё Развернуть
var input = "Строчка с 3 числами в ней... 42 и 88.";
var number = /\b(\d+)\b/g;
var match;
while (match = number.exec(input))
  console.log("Нашёл ", match[1], " на ", match.index);
// → Нашёл 3 на 14
//   Нашёл 42 на 33
//   Нашёл 88 на 40

Используется тот факт, что значением присвоения является присваиваемое значение. Используя конструкцию match = re.exec(input) в качестве условия в цикле while, мы производим поиск в начале каждой итерации, сохраняем результат в переменной, и заканчиваем цикл, когда все совпадения найдены.

цикл, вхождение, lastindex, exec, match, re.exec, while,

Разбор INI файлы

Admin » » Сообщение:

Рассмотрим задачу с использованием регулярок. Представьте, что мы пишем программу, собирающую сведения о наших врагах через интернет в автоматическом режиме. (Всю программу писать не будем, только ту часть, которая читает файл с настройками. Извините.) Файл выглядит так:

Код: Выделить всё Развернуть
searchengine=http://www.google.com/search?q=$1
spitefulness=9.7

; перед комментариями ставится точка с запятой
; каждая секция относится к отдельному врагу
[larry]
fullname=Larry Doe
type=бычара из детсада
website=http://www.geocities.com/CapeCanaveral/11451

[gargamel]
fullname=Gargamel
type=злой волшебник
outputdir=/home/marijn/enemies/gargamel

Точный формат файла (который довольно широко используется, и обычно называется INI), следующий:

- пустые строки и строки, начинающиеся с точки с запятой, игнорируются
- строки, заключенные в квадратные скобки, начинают новую секцию
- строки, содержащие алфавитно-цифровой идентификатор, за которым следует =, добавляют настройку в данной секции

Все остальное - неверные данные.

Наша задача - преобразовать такую строку в массив объектов, каждый со свойством name и массивом настроек. Для каждой секции нужен один объект, и еще один - для глобальных настроек сверху файла.

Так как файл надо разбирать построчно, неплохо начать с разбиения файла на строки. Для этого в главе 6 мы использовали string.split("\n"). Некоторые операционки используют для перевода строки не один символ \n, а два - \r\n. Так как метод split принимает регулярки в качестве аргумента, мы можем делить линии при помощи выражения /\r?\n/, разрешающего и одиночные \n и \r\n между строками.

Код: Выделить всё Развернуть
function parseINI(string) {
// Начнем с объекта, содержащего настройки верхнего уровня
var currentSection = {name: null, fields: []};
var categories = [currentSection];

string.split(/\r?\n/).forEach(function(line) {
var match;
if (/^\s*(;.*)?$/.test(line)) {
return;
} else if (match = line.match(/^\[(.*)\]$/)) {
currentSection = {name: match[1], fields: []};
categories.push(currentSection);
} else if (match = line.match(/^(\w+)=(.*)$/)) {
currentSection.fields.push({name: match[1],
value: match[2]});
} else {
throw new Error("Строчка '" + line + "' содержит неверные данные.");
}
});

return categories;
}

Код проходит все строки, обновляя объект текущей секции “current section”. Сначала он проверяет, можно ли игнорировать строчку, при помощи регулярки /^\s*(;.*)?$/.
Соображаете, как это работает?
Часть между скобок совпадает с комментариями, а? делает так, что регулярка совпадет и со строчками, состоящими из одних пробелов.

Если строка - не комментарий, код проверяет, начинает ли она новую секцию. Если да, он создает новый объект для текущей секции, к которому добавляются последующие настройки.

Последняя осмысленная возможность - строка является обычной настройкой, и в этом случае она добавляется к текущему объекту.

Если ни один вариант не сработал, функция выдает ошибку.

Заметьте, как частое использование ^ и $ заботится о том, что выражение совпадает со всей строкой целиком, а не с частью. Если их не использовать, код в целом будет работать, но иногда будет выдавать странные результаты, и такую ошибку будет трудно отследить.

Конструкция if (match = string.match(...)) похожа на трюк, использующий присвоение как условие в цикле while. Часто вы не знаете, что вызов match будет успешным, поэтому вы можете получить доступ к результирующему объекту только внутри блока if, который это проверяет. Чтоб не разбивать красивую цепочку проверок if, мы присваиваем результат поиска переменной, и сразу используем это присвоение как проверку.

разбор, ini файлы, string, split, while, match,

Международные символы

Admin » » Сообщение:

Из-за изначально простой реализации языка, и последующей фиксации такой реализации «в граните», регулярки JavaScript тупят с символами, не встречающимися в английском языке. К примеру, символ «буквы» с точки зрения регулярок JavaScript, может быть одним из 26 букв английского алфавита, и почему-то еще подчеркиванием. Буквы типа é или β, однозначно являющиеся буквами, не совпадают с \w (и совпадут с \W, то есть с не-буквой).

По странному стечению обстоятельств, исторически \s (пробел) совпадает со всеми символами, которые в Unicode считаются пробельными, включая такие штуки, как неразрывный пробел или монгольский разделитель гласных.

У некоторых реализаций регулярок в других языках есть особый синтаксис для поиска специальных категорий символов Unicode, типа «все прописные буквы», «все знаки препинания» или «управляющие символы». Есть планы по добавлению таких категорий и в JavaScript, но они, видимо, будут реализованы не скоро.

unicode, символ, регулярка

Итог

Admin » » Сообщение:

Регулярки - это объекты, представляющие шаблоны поиска в строках. Они используют свой синтаксис для выражения этих шаблонов.

/abc/ Последовательность символов
/[abc]/ Любой символ из списка
/[^abc]/ Любой символ, кроме символов из списка
/[0-9]/ Любой символ из промежутка
/x+/ Одно или более вхождений шаблона x
/x+?/ Одно или более вхождений, нежадное
/x*/ Ноль или более вхождений
/x?/ Ноль или одно вхождение
/x{2,4}/ От двух до четырех вхождений
/(abc)/ Группа
/a|b|c/ Любой из нескольких шаблонов
/\d/ Любая цифра
/\w/ Любой алфавитно-цифровой символ («буква»)
/\s/ Любой пробельный символ
/./ Любой символ, кроме переводов строки
/\b/ Граница слова
/^/ Начало строки
/$/ Конец строки

У регулярки есть метод test, для проверки того, есть ли шаблон в строке. Есть метод exec, возвращающий массив, содержащий все найденные группы. У массива есть свойство index, показывающее, где начался поиск.

У строк есть метод match для поиска шаблонов, и метод search, возвращающий только начальную позицию вхождения.
Метод replace может заменять вхождения шаблона на другую строку. Кроме этого, вы можете передать в replace функцию, которая будет строить строчку на замену, основываясь на шаблоне и найденных группах.

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

Конструктор RegExp можно использовать для создания регулярок из строк.

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

регулярки, объекты, шаблоны, поиск, строки, синтаксис, выражения, test, exec, index, match, search, replace, regexp

инструменты, регулярка

Re: Выразительный JavaScript: Регулярные выражения

koeshiro » » Сообщение:

Я просто оставлю это тут.
Замена type of понимающая array, html, ...

Код: Выделить всё Развернуть
function type(e){var t=Object.prototype.toString.call(e);if(/\[object HTML([a-zA-Z]+)Element\]/.test(t)) return t.match(/\[object HTML([a-zA-Z]+)Element\]/)[1].toLowerCase();else if(/\[object ([a-zA-Z]+)\]/.test(t)) t.match(/\[object ([a-zA-Z]+)\]/)[1].toLowerCase();}

Пред.



Похожие темыКомментарии ПросмотрыПоследнее сообщение
0920JavaScript. Логические операторы и ...
Сообщение от: Admin
03057Дженнифер Нидерст Роббинс. HTML5, C...
Сообщение от: Admin
0493JavaScript методы alert, document.w...
Сообщение от: Admin
0667Колонки одинаковой высоты - лучшее ...
Сообщение от: Admin
0619Замена прямых кавычек на “ёлочки”. ...
Сообщение от: Admin