Низкоуровневое обнаружение (LLD) в Zabbix через SQL-запросы

Низкоуровневое обнаружение (LLD) в Zabbix через SQL-запросы Хостинг

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 1

Всем привет, ранее мы уже упоминали о возможностях по массовому сбору данных в новой версии опенсорс системы мониторинга Zabbix 3.4. Теперь остановимся на этом функционале поподробнее, и чтобы было нагляднее, расскажем о нем на двух примерах:

  • сбор всех данных за раз, полученных в JSON от консольной утилиты счетчика электроэнергии Меркурий 236
  • сбор показателей S.M.A.R.T. жестких дисков и SSD, полученных в табличном виде от smartmontools.

А в чем была собственно проблема?

Собирать данные через консольные утилиты или вызовы API данные можно было и ранее, но существовали сложности:

  • медленные запуски утилит каждый раз, на каждый нужный элемент данных
  • обращение к ресурсу (диск, порт, счетчик, API приложения) на каждый элемент данных
  • парсинг результата нужно было делать внешними скриптами/утилитами
  • а если потом нужно было поправить парсинг – приходилось опять обновлять UserParameters или скрипты
  • кроме всего прочего, одновременные запросы от нескольких Zabbix pollers приводили к ошибке при обращении, например, к последовательному порту.

В общем, дело было так:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 2

А с появлением зависимых элементов данных, стало возможно так:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 3

Как это работает?

  • В Zabbix 3.4 источником данных может выступать другой элемент данных, который называется родительским или мастер-элементом. Такой элемент может, например, содержать массив данных в формате JSON, XML или фривольном текстовом формате.
  • В момент поступления новых данных в родительский элемент, остальные элементы данных, которые называются зависимыми, обращаются к родительскому элементу и при помощи таких функций препроцессинга как JSON path, XPath или Regex выделяют из текста нужную метрику.

Кстати, препроцессинг – тоже нововведение 3.4, он реализован добавлением новых процессов preprocessing_manager и preprocessing_worker на Zabbix-сервере. Поэтому, если вы обновляетесь с 3.2 – не забудьте обновить шаблон для сервера, чтобы мониторить их работу.

Переходим к примерам.

Меркурий 236

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 4

Представим, что на нашем проекте, кроме контейнеров, виртуальных машин, приложений, сетевых устройств, баз данных, бизнес показателей и всего прочего требующего контроля, присутствует необходимость мониторить показатели электросети и другой «инженерки», как, например, климатическое оборудование. Используются стандартные для нашей средней полосы устройства: трехфазный счетчик электроэнергии Меркурий 236 АRT-01 PQRS с интерфейсом RS-485, поверх которого общение происходит через проприетарный протокол производителя.
Задача ответственная – сразу собирать показатели напряжения, мощности, тока, потребления, частоты. Подключить такой прибор к серверу с Zabbix агентом – задача посильная – достаточно будет серийного порта с RS-485, например, в форме USB адаптера. Но как прочитать данные? Если бы не github и добрые люди, поделившиеся своим решением для умного дома, писать бы нам модуль к Zabbix, который бы мы учили разговаривать на протоколе счетчика и опрашивать показатели.
Утилита простая и удобная (за что автору большое человеческое спасибо) подключается к счетчику на указанный порт, считывает данные и отдает нам в виде текста, CSV или JSON.

Давайте попробуем установить и запустить:

Запускается! Отлично, подключаем счетчик, опрашиваем, получаем JSON:

./mercury236 /dev/ttyS0 —json

{
                "U": {
                               "p1": 0.35,
                               "p2": 0.35,
                               "p3": 226.86
                },
                "I": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 0.39
                },
                "CosF": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 0.60,
                               "sum": 0.60
                },
                "F": 50.00,
                "A": {
                               "p1": 41943.03,
                               "p2": 41943.03,
                               "p3": 41943.03
                },
                "P": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 53.45,
                               "sum": 53.45
                },
                "S": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 89.83,
                               "sum": 89.83
                },
                "PR": {
                               "ap": 120.51
                },
                "PR-day": {
                               "ap": 86.00
                },
                "PR-night": {
                               "ap": 34.51
                },
                "PY": {
                               "ap": 0.00
                },
                "PT": {
                               "ap": 0.04
                }
}

В итоге утилита уже сделала всю сложную работу за нас, реализовав протокол общения с счетчиком, вытащив данные, да еще и предложила нам это в виде удобного JSON объекта. Вот только раньше просто так мы ей не смогли бы воспользоваться — пришлось бы писать обвязку в виде скриптов, а самое главное – реализовывать механизм контроля доступа к среде последовательного порта. Ведь если два поллера Zabbix одновременно обратятся к нему – один за током третьей фазы 3, а другой — за током фазы 2, у нас не вернулось бы ничего.
В 3.4 все становится гораздо проще, и мы теперь быстро и легко можем передавать данные сторонних консольных утилит в Zabbix, не прибегая к оберточным скриптам, и не запуская по 10 раз одно и тоже на каждый элемент данных отдельно. Итак,

Читайте также:  Защитите свою сеть с помощью Easy Mikrotik Login: начните сегодня

Настроим запуск утилиты mercury236 из Zabbix

UserParameter=mercury236[*],/etc/zabbix/scripts/mercury236 $1 $2

Сохраняем файл, не забываем перезапустить наш Zabbix-агент.
Теперь создадим в новом шаблоне родительский элемент данных:

Настроим получение наших метрик счетчика

Для того чтобы начать создавать зависимые элементы данных, можно воспользоваться новым помощником. Ну или просто нажать «Создать элемент данных»:

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 6

Создадим элемент данных для напряжения первой фазы, выберем:

  • Тип: Зависимый элемент данных
  • Основной элемент данных: mercury-get

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 7

Затем во вкладке «Предобработка» добавим наше выражение JSON Path:
Путь JSON: $.U.p1
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 8

Кстати, маленький совет. Чтобы не тратить много времени на отладку и ловлю ошибок, перед тем как заполнять JSON Path можно быстро проверить правильность выражения онлайн, например здесь: jsonpath.com, скопировав туда JSON, полученный от утилиты.
Аналогичным образом создаем другие интересующие нас метрики. В том числе — для накопленной энергии по дневному тарифу.

Для этого создадим новый элемент данных и выберем:

  • Тип: Зависимый элемент данных
  • Основной элемент данных: mercury-get

А вот во вкладке «Предобработка» обратите внимания на два нюанса:

  • будем использовать нотацию с квадратными скобками, так как в пути JSON есть дефис
  • препроцессинг может быть многошаговым, например здесь результата первого шага умножим на 1000, чтобы получить Вт*ч из кВт*ч

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 9

Проделаем аналогично для остальных ключевых метрик счетчика, в итоге получим вот такой список:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 10

Доведем наш шаблон до ума

Чтобы шаблон был законченным, добавим триггеры, используя макросы, делая его максимально гибким. Не забываем про зависимости триггеров.
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 11

Что получилось

Шаблон готов, данные побежали, посмотрим, что у нас получилось:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 12

Все последние данные, собранные за одно обращение:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 13

  • переиспользовали хорошую программку и не тратили время на написание своей реализации сбора данных по протоколу Меркурий
  • UserParameter остался, но схлопнулся до простого вызова. По сути можно даже system.run[] использовать
  • cкрипты-обертки тоже не писали. Всё распарсили через JSON path в шаблоне
  • cчетчик не мучали сильно, один запрос – все нужные нам данные разом.

Smartctl и smartmontools

  • избыточные запуски утилиты smartctl, а она в свою очередь каждый раз обращалась к контроллеру жесткого диска
  • пришлось делать отдельный парсинг для Linux и Windows. Особенно больно с этим сейчас работать в Win: (for /F… так… экранируем двойные кавычки еще кавычками…. Аааа!!!!)

Постараемся в 3.4 от всего этого избавится.

Случай с smartmontools имеет два отличия от примера со счетчиком выше:

  • smartctl нам JSON не возвращает
  • дисков в сервере может быть различное количество, поэтому нам нужно использовать низкоуровневое обнаружение(LLD).

Но ничего страшного! Во-первых, зависимые элементы данных работают и для LLD, а во-вторых у нас среди preprocessing-фильтров есть и PCRE regex. Воспользуемся им, чтобы вытащить нужные показатели из не супер сильно структурированного ответа утилиты. Примерно такого:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 15

Приступим.

Упрощаем UserParameters

UserParameter=uHDD[*], sudo smartctl -A $1| grep -i "$2"| tail -1| cut -c 88-|cut -f1 -d' '
UserParameter=uHDD.model.[*],sudo smartctl -i $1 |grep -i "Device Model"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.sn.[*],sudo smartctl -i $1 |grep -i "Serial Number"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.health.[*],sudo smartctl -H $1 |grep -i "test"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.errorlog.[*],sudo smartctl -l error $1 |grep -i "ATA Error Count"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.discovery,sudo /etc/zabbix/scripts/smartctl-disks-discovery.pl
UserParameter=uHDD.A[*],sudo smartctl -A $1
UserParameter=uHDD.i[*],sudo smartctl -i $1
UserParameter=uHDD.health[*],sudo smartctl -H $1
UserParameter=uHDD.discovery,sudo /etc/zabbix/scripts/smartctl-disks-discovery.pl

Аналогично делаем и для Windows, попутно избавляясь от CMD магии с использование for /F и find. Посмотреть можно тут.

Читайте также:  Шлюз CentOS по умолчанию: как настроить за 5 простых шагов

Создаем новые родительские элементы данных

Для сбора всех атрибутов S.M.A.R.T. создадим прототип мастер-элемента данных:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 16

Как и в предыдущем примере, ничего особенного настраивать не надо. Только Тип информации – Text, а Период хранения — 1 день.
Для сбора результатов тестов и инвентарных данных нам потребуется запускать smartctl с другими ключами. Поэтому аналогично создадим еще два элемента данных:

  • uHDD.i[«{#DISKNAME}»]
  • uHDD.health[«{#DISKNAME}»]

Настроим получение наших атрибутов S.M.A.R.T. диска

Создадим зависимый элемент данных для атрибута 5, Reallocated:

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 17

И во вкладке «Предобработка» используем регулярное выражение:

Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 18

И так же как и с JSON Path, чтобы не тратить много времени на отладку и ловлю ошибок, перед тем как заполнять regex, удобно быстро проверить правильность выражения онлайн, например здесь: regex101.com скопировав туда наш вывод smartctl.
В итоге получим такой вот список прототипов:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 19

Тестируем, смотрим что получилось

Для двух HDD:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 20

Для SSD под Windows:
Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools - 21

Подведем итоги примера с smartmontools:

  • мы убрали весь парсинг из UserParameters
  • нет внешних скриптов (кроме LLD), нет внешних зависимостей, весь парсинг происходит на Zabbix-сервере, там его легко посмотреть и подправить, если нужно
  • когда утилита или API не возвращает XML/JSON – не беда, всегда можно попробовать использовать регулярные выражения
  • жесткие диски больше не мучаем – сначала достаем весь список параметров S.M.A.R.T., а затем уже на Zabbix-сервере раскладываем его по метрикам.

В завершении

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

Пример данных для 1 диска

Код: Выделить всё

{
"hddList":{
"hdd":{
"id":"2",
"hddName":"hdd2",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"1714176",
"property":"RW"
}}}

Код: Выделить всё

{
"hddList":{
"hdd":[
{
"id":"1",
"hddName":"hdda",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"0",
"property":"RW"
},
{
"id":"2",
"hddName":"hddb",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"0",
"property":"RW"
}
]}}
Предобработка JS обнаружение дисков
Предобработка JS обнаружение дисков

Код: Выделить всё

var data = JSON.parse(value);
var out = [];

  data.hddList.hdd.forEach(function (field) {
   out.push({
     "{#HDD_ID}": field.id,
     "{#HDD_NAME}": field.hddName,
     "{#HDD_PATH}": field.hddPath,
     "{#HDD_TYPE}": field.hddType
            });
  })

//return JSON.stringify(out);
// Читаемый вид перенос строк              
return JSON.stringify(out).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");
Предобработка JS обнаружение дисков результат
Предобработка JS обнаружение дисков результат

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

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";

//data.hddList.hdd = data.hddList.hdd.map((padObj) => Object.assign({}, padObj, {hdd: [padObj.hdd]}));

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {

  var test = data.hddList.hdd
test.forEach(function (key) {

// Получим данные для типа диска
   out.push({
     "{#HDD_ID}": key.id,
     "{#HDD_NAME}": key.hddName,
     "{#HDD_PATH}": key.hddPath,
     "{#HDD_TYPE}": key.hddType
         });
 // Одной строкой
 //    out.push({"{#HDD_ID}": key.id,"{#HDD_NAME}": key.hddName,"{#HDD_PATH}": key.hddPath,"{#HDD_TYPE}": key.hddType});
})}
//masd+= out;

//return JSON.stringify(out);
// Читаемый вид перенос строк              
return JSON.stringify(out).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");
//return JSON.stringify(masd).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");

Код: Выделить всё

var out = [];
for (var i = 0; i < 3; i++) {
    var objekt = {};
    objekt['{#HDD_ID}'] = 2;
    objekt['{#HDD}'] = 'hdd';
    objekt['{#HDD_NAME}'] = 'hdd' + i;
    objekt['{#HDD_NAME}'] = '';
    objekt['{#HDD_TYPE}'] = 'SATA';
    out.push(objekt);;
}

return JSON.stringify(out);

Инфо о json-stringify

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {

  var test = data.hddList.hdd
var out = [];
for (var i = 0; i < 3; i++) {
    var objekt = {};
    objekt['{#HDD_ID}'] = 2;
    objekt['{#HDD}'] = 'hdd';
    objekt['{#HDD_NAME}'] = 'hdd' + i;
    objekt['{#HDD_NAME}'] = '';
    objekt['{#HDD_TYPE}'] = 'SATA';
    out.push(objekt);;
}}

return JSON.stringify(out);

Пятый Вариант Скрипта
Входные данные

Код: Выделить всё

{ "hddList":{
"hdd":
{ "id":"2", "hddName":"hdd2", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"5723166", "freeSpace":"1714176", "property":"RW" }, 
"hdd":
{ "id":"3", "hddName":"hdd3", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"5893165", "freeSpace":"3717179", "property":"RW" },
"ssd":
{ "id":"4", "hddName":"hdd4", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"89359", "freeSpace":"5479215", "property":"RS" }
}}

Код: Выделить всё

const myJson = value
const re = new RegExp(/([^"]+)"\s{0,}:\s{0,}{\s{0,}"id"/, 'gim');

var count = 0;
result = myJson.replace(re, function(match) {
        count++;
        return count + "_" + match;
    })
    data = JSON.parse(result),
    massiv = [];

for ( key in data.hddList) {
    massiv.push(data.hddList[key]);
}

return JSON.stringify(massiv);

Эксперименты ко Второму варианты

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";
var dataout = "";

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {
// Накопительная переменная, диски
dataout+= typeofdisk+"\n";
}
return dataout;

Эксперимент с данными виде текста не json

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"[A-Za-z0-9]+":{"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("" + regexp).split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
    //var idn = (myarray[i]).replace(/\[|]/gi, '');
    var idn = "\"id\":\"\d+\""
    // console.log(myarray[i], myarray[i].match(/"id":"(\d+)"/gmi));
    var res = myarray[i].match(/"id":"(\d+)"/);
    // если нашли число
    if ( res[1] >= 0 ) {
        // удаляем данные об ИД и добавялем ИД к названию диска
        myarray[i] = myarray[i].replace(/:{"id":"(\d+)"/, "").replaceAll("\"", "");

        //выводим имя диска в консоль:
        console.log(myarray[i]);
        //выводим ид диска в консоль
        console.log(res[1]);
    }
}

Метод str.match(regexp), если у регулярного выражения regexp
нет флага g, ищет первое совпадение и возвращает его в виде массива:

Читайте также:  Хостинг с неограниченным дисковым пространством: идеальное решение для вашего сайта

Далее будем работать с такими данными
Тестовые данные

Код: Выделить всё

{
"hddList":{
"hdd":{
"id":"2",
"hddName":"hdd2",
"hddPath":"",
"hddType":"SATA2",
"status":"ok",
"capacity":"5723166",
"freeSpace":"1714176",
"property":"RW"
},
"hdd":{
"id":"3",
"hddName":"hdd3",
"hddPath":"",
"hddType":"SATA3",
"status":"ok",
"capacity":"5893165",
"freeSpace":"3717179",
"property":"RW",
"id":"5",
"hddName":"hdd5",
"hddPath":"",
"hddType":"SATA5",
"status":"ok",
"capacity":"893559",
"freeSpace":"54759215",
"property":"RS5"
},
"ssd":{
"id":"4",
"hddName":"hdd4",
"hddPath":"",
"hddType":"SATA4",
"status":"ok",
"capacity":"89359",
"freeSpace":"5479215",
"property":"RS"
}}}

Начало разработки тестируем

Код: Выделить всё

// Найдем все ID
var regexp = value.match(/"id":"[0-9]+"/gmi);
// запятую заменим на перенос строк
//var test = ("[" + regexp + "]").replace(/\,/g,"\n");
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');
var idn = "id\":\"3\"";
// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем название дисков
test = diskval.match(new RegExp(([A-z]+)":{" idn,'gim'));
return test

//return listdis ;
}

СРАЗУ НУЖНЫЙ БЛОК С ДИСКОМ

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);
// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');
var idn = "\"id\":\"2\""
// Выберем название дисков
testx = "[" + diskid + "]";
test = testx.match(/[A-z0-9.]+/g,"");
//.match(new RegExp(idn,'gim'));
return testx
//return listdis ;
}

Выведем ID и Тип Диска который перед ID

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');

// Выберем название дисков, для соответствующего ID ,с фиксированными переменными ID
diskids = "[" + diskid + "]";
//test = diskids.match(/[A-z0-9.]+/g,"");
//.match(new RegExp(idn,'gim'));
// Формирование регулярного выражения с текущим ID
var idn = "\"([A-z0-9.]+)\":{|\"id\":\"5\""
// Текущее ID с названиям дисков
namediskid =diskids.match(new RegExp(idn,'gim'));
namediskids ="[" + namediskid + "]"
// Формирование регулярного выражения с текущим ID
var idx = "\"([A-z0-9.]+)\":{,\"id\":\"5\""
// Имя диска и текущий ID
nameid =namediskids.match(new RegExp(idx,'gim'));
nameids = "[" + nameid + "]";
// Оставляем только Имя диска
hddName =nameids.match(/"(([A-z0-9.]+))":{/im);
return hddName[1];
}

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i)
for (var i = 0; i < myarray.length; i++){
var idv = (myarray[i]).replace(/\[|]/gi, '').replace(/"/gi,"\\\"");
var res = myarray[i].match(/"id":"(\d+)"/);

// Выберем название дисков, для соответствующего ID
diskids = "[" + diskid + "]";
// Формирование регулярного выражения с текущим ID
var idn = '\"([A-z0-9.]+)\":{|'+idv+''

//var idn = "\"([A-z0-9.]+)\":{|\"id\":\"${res[1]}\""
// Текущее ID с названиям дисков
namediskid =diskids.match(new RegExp(idn,'gim'));
namediskids ="[" + namediskid + "]"
// Формирование регулярного выражения с текущим ID
var idx = '\"([A-z0-9.]+)\":{,'+idv+''
//var idx = "\"([A-z0-9.]+)\":{,\"id\":\"${res[1]}\""
// Имя диска и текущий ID
nameid =namediskids.match(new RegExp(idx,'gim'));
nameids = "[" + nameid + "]";
// Оставляем только Имя диска
DiskListName =nameids.match(/"(([A-z0-9.]+))":{/im);
var DiskList =DiskListName[1];
return DiskList;
}

И ГОТОВЫЙ ВАРИАНТ СКРИПТА

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"").replace(/[\[\]]+/g,"");
// Выберем Вид Диска + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Переменные
var sep="";
var dataout = "";

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i)
for (var i = 0; i < myarray.length; i++){
// Подстановка ID в регулярку
var idv = (myarray[i]).replace(/\[|]/gi, '').replace(/"/gi,"\\\"");
// ID
var ID = idv.match(/([0-9]+)/gmi)

// Выберем Вид дисков, для соответствующего ID
diskids = "[" + diskid + "]";
// Текущее ID с видом дисков, регулярного выражения с текущим ID
viddiskid =diskids.match(new RegExp('\"([A-z0-9.]+)\":{|'+idv+'','gim'));
viddiskids ="[" + viddiskid + "]"
// Вид диска и текущий ID, регулярного выражения с текущим ID
vidid =viddiskids.match(new RegExp('\"([A-z0-9.]+)\":{,'+idv+'','gim'));
vidids = "[" + vidid + "]";
// Оставляем только Вид диска
DiskListVid =vidids.match(/"(([A-z0-9.]+))":{/im);
// Вид диска
var DiskList =DiskListVid[1];
// Имя Диска
var diskname =diskval.match(new RegExp('\"id\":\"'+ID+'\",\"hddName\":\"([A-z0-9.]+|)\"','im'));
// Путь Диска
var diskpath =diskval.match(new RegExp('\"id\":\"'+ID+'\".*?,\"hddPath\":\"([A-z0-9.]+|)\"','im'));
// Тип Диска
var disktype =diskval.match(new RegExp('\"id\":\"'+ID+'\".*?,\"hddType\":\"([A-z0-9.]+|)\"','im'));
// Строка с данными
sop=''+sep+'{"{#HDD_ID}": "'+ID+'", "{#DISKLIST}": "'+DiskList+'", "{#HDD_NAME}": "'+diskname[1]+'", "{#HDD_PATH}": "'+diskpath[1]+'", "{#HDD_TYPE}": "'+disktype[1]+'"}';
var sep=",";
// Накопительная переменная для цикла
dataout+= sop;
}
// Добавим скобки массива, для объекта
out = "[" + dataout + "]";
//return out;
// Читаемый вид перенос строк              
return out.replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");

Оцените статью
Хостинги