v8: Простой анализ текстовых строк по маркерам в тексте Ключевые слова: строки,маркеры,парсинг,регулярные выражения
У меня была такая строка в Excel, нужно было выделить из нее две суммы - сумму за электроэнергию и сумму за мощность.
42 418 838 руб.,
15 коп. за
электроэнергию
за период
с 01.01
по 06.01
12 148 608 руб.,
06 коп. за
мощность
Программист, который работал до меня, тупо ориентировался на позицию строки "Электроэнергию", в общем код был такой:
Функция РаспознатьСуммыПлатежей(ЗнЯчейки)
СтрЭ = Прав(СтрЭ,СтрДлина(СтрЭ) - руб-4);
коп = Найти(СтрЭ,"коп");
КопЭ = ___обВЧислоИлиНоль(СтрЗаменить(СокрЛП(Лев(СтрЭ,коп-1))," ",""));
// Мощность
Э = Найти(ЗнЯчейки,"электроэнергию");
СтрЭ = Лев(ЗнЯчейки,Э - 1);
СтрМ = Прав(ЗнЯчейки,СтрДлина(ЗнЯчейки) - Э - 14);
СтрП = Найти(СтрМ,"за период");
Если СтрП = 1 Тогда
СтрМ = Прав(СтрМ,СтрДлина(СтрМ) - 36);
КонецЕсли;
// Электроэнергия
руб = Найти(СтрЭ,"руб");
РубЭ = ___обВЧислоИлиНоль(СтрЗаменить(СокрЛП(Лев(СтрЭ,руб-1))," ",""));
СтрЭ = Прав(СтрЭ,СтрДлина(СтрЭ) - руб-4);
коп = Найти(СтрЭ,"коп");
КопЭ = ___обВЧислоИлиНоль(СтрЗаменить(СокрЛП(Лев(СтрЭ,коп-1))," ",""));
// Мощность
руб = Найти(СтрМ,"руб");
РубМ = ___обВЧислоИлиНоль(СтрЗаменить(СокрЛП(Лев(СтрМ,руб-1))," ",""));
СтрМ = Прав(СтрМ,СтрДлина(СтрМ) - руб-4);
коп = Найти(СтрМ,"коп");
КопМ = ___обВЧислоИлиНоль(СтрЗаменить(СокрЛП(Лев(СтрМ,коп-1))," ",""));
Возврат Новый Структура("Ошибка, РубМ, КопМ, РубЭ, КопЭ", ложь, РубМ, КопМ, РубЭ, КопЭ);
КонецФункции
Но потребовалось более интеллектуальное распознавание, т.к. иногда год записывали через два знака, иногда через четыре, в результате такое позиционирование не годилось.
Я использовал распознавание, ориентированное на маркеры:
Функция РаспознатьСуммыПлатежей(ЗнЯчейки)
М=Новый Массив();
М.Добавить("руб");
М.Добавить("коп");
М.Добавить("по");
М.Добавить(Символы.ПС);
М.Добавить("руб");
М.Добавить("коп");
Р=___обСоответствиеСтрокиМаркерам(ЗнЯчейки, М);
Если Р=Неопределено Тогда
Возврат Новый Структура("Ошибка, РубМ, КопМ, РубЭ, КопЭ", истина, 0, 0, 0, 0);
КонецЕсли;
РубЭ = Число(___обИзвлечьЦифрыИзСтроки(Р[0]));
КопЭ = Число(___обИзвлечьЦифрыИзСтроки(Р[1]));
РубМ = Число(___обИзвлечьЦифрыИзСтроки(Р[4]));
КопМ = Число(___обИзвлечьЦифрыИзСтроки(Р[5]));
Возврат Новый Структура("Ошибка, РубМ, КопМ, РубЭ, КопЭ", ложь, РубМ, КопМ, РубЭ, КопЭ);
КонецФункции
//fixin 20080212
//Извлекает цифры из строки, только цифры
//Возвращает строку с цифрами
Функция ___обИзвлечьЦифрыИзСтроки(С)
Р="";
Для Инд=1 По СтрДлина(С) Цикл
Симв=Сред(С, Инд, 1);
Если Найти("0123456789", Симв)<>0 Тогда
Р=Р+Симв;
КонецЕсли;
КонецЦикла;
Возврат Р;
КонецФункции
//fixin 20080212
//Ищет в строке С маркеры М и выдает массив разбиений
//Если разложить не получилось, то выдает Неопределено
//Пример:
// "100 руб. 50 коп.", {"руб","коп"} => {"100 " ". 50 ", "."}
// "100 руб", {"руб","коп"} => Неопределено
Функция ___обСоответствиеСтрокиМаркерам(_С, М, УчитыватьРегистр=ложь)
Перем С, ДлинаСтроки, Р, ТекСтрока, Поз, ДлинаМаркера, ТекМаркер, ИскМаркер;
Если УчитыватьРегистр Тогда
С=_С;
Иначе
С=ВРег(_С);
КонецЕсли;
ДлинаСтроки=СтрДлина(С);
//Массив для возврата
Р=Новый Массив();
ТекСтрока=""; //Текущая строка для анализа
//Позиция анализа
Поз=1;
ТекСтрока="";
//Ищем очередной маркер
НайденоМаркеров=0;
Для Каждого ЭлМаркер Из М Цикл
ДлинаМаркера=СтрДлина(ЭлМаркер);
Если УчитыватьРегистр Тогда
ТекМаркер=ЭлМаркер;
Иначе
ТекМаркер=ВРег(ЭлМаркер);
КонецЕсли;
Пока (Поз<=ДлинаСтроки) Цикл
//Смотрим, получаем ли мы текущий маркер в текущей позиции
ИскМаркер=Сред(С, Поз, ДлинаМаркера);
Если ИскМаркер=ТекМаркер Тогда
Р.Добавить(ТекСтрока);
ТекСтрока="";
НайденоМаркеров=НайденоМаркеров+1;
Поз=Поз+ДлинаМаркера; //Сдвигаем позицию
Прервать;
КонецЕсли;
ТекСтрока=ТекСтрока+Сред(С, Поз, 1);
Поз=Поз+1;
КонецЦикла;
КонецЦикла;
Р.Добавить(Сред(С, Поз)); //Хвостик добавляем
Если НайденоМаркеров=М.Количество() Тогда
Возврат Р;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Такое распознавание проще и надежнее. Проще, чем регулярные выражения. рекомендую.
|