Выразительный JavaScript (Хавербеке) - страница 101

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

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

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

>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). Сначала он проверяет, можно ли игнорировать строчку, при помощи регулярки