Загрузка данных
// Упаковываем шаблоны (строки) регулярных выражений в структуру.
// (?i) - включает игнорирование регистра в самом шаблоне.
Шаблоны = Новый Структура;
// Для СтрПодобнаПоРегулярномуВыражению (требует совпадения всей строки, добавляем .* в конец)
Шаблоны.Вставить("Начало", "(?i)^(Авиабилет|Электронный|Ж/д|Автобусный|Сверхнормативный|Доплата|а/б).*");
// Для СтрНайтиПоРегулярномуВыражению и СтрЗаменитьПоРегулярномуВыражению
Шаблоны.Вставить("Тип", "(?i)^(Авиабилет|Электронный ж/д билет|Ж/д билет|Автобусный билет|Сверхнормативный багаж[^(]*|Доплата за обмен[^(]*|а/б)");
Шаблоны.Вставить("Перевозчик", "(?i)\(\s*перевозчик\s*(.*?)(?:,\s*ИНН\s*(\d*))?\s*\)");
Шаблоны.Вставить("Класс", "(?i)\((Эконом|Купе|Плацкарт|Сидячий)\)");
Шаблоны.Вставить("Дата", "(?i)(\d{2}\.\d{2}\.\d{4}(?:\/\d{2}\.\d{2}\.\d{4})?)");
// Шаблон для "Номер Маршрут" (используется, когда дата найдена)
Шаблоны.Вставить("НомерМаршрут", "(?i)^([A-Za-z0-9\s/\.\-]+?)\s+([А-Яа-яЁёA-Za-z].*)$");
// Шаблон для бездатных билетов: строго извлекает "Номер", "Маршрут" и "ФИО" (с инициалами или из 3-х слов)
Шаблоны.Вставить("Бездатный", "(?i)^([A-Za-z0-9\s/\.\-]+?)\s+(.*?)\s+([А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z]\s*\.?\s*[А-Яа-яЁёA-Za-z]\s*\.*|[А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z\-]+)\s*$");
// Мусор для очистки номеров
Шаблоны.Вставить("МусорСлеш", "(?i)(к билету\s*№|Новый а/б\s*№)");
Шаблоны.Вставить("МусорУдалить", "(?i)(Квитанция\s*№|Исходный а/б\s*№|а/б\s*№|№)");
// Выполняет пошаговый разбор одной склеенной строки билета
Функция РаспарситьСтрокуБилета(Знач СтрокаБилета, Шаблоны)
ДанныеБилета = Новый Структура;
ДанныеБилета.Вставить("ТипБилета", "");
ДанныеБилета.Вставить("Перевозчик", "");
ДанныеБилета.Вставить("ИНН", "");
ДанныеБилета.Вставить("НомерБилета", "");
ДанныеБилета.Вставить("Маршрут", "");
ДанныеБилета.Вставить("Дата", "");
ДанныеБилета.Вставить("Класс", "");
ДанныеБилета.Вставить("Пассажир", "");
ДанныеБилета.Вставить("ДопИнфо", "");
ДанныеБилета.Вставить("ИсходнаяСтрока", СтрокаБилета);
ОстатокСтроки = СтрокаБилета;
// ШАГ 1: Тип билета
ДанныеБилета.ТипБилета = ИзвлечьТипБилета(ОстатокСтроки, Шаблоны.Тип);
// ШАГ 2: Перевозчик и ИНН
ЗаполнитьЗначенияСвойств(ДанныеБилета, ИзвлечьПеревозчикаИИнн(ОстатокСтроки, Шаблоны.Перевозчик));
// ШАГ 3: Класс обслуживания
ДанныеБилета.Класс = ИзвлечьКлассБилета(ОстатокСтроки, Шаблоны.Класс);
// ШАГ 4 и 5: Обработка оставшейся строки (Дата, Пассажир, ДопИнфо, Номер, Маршрут)
ДанныеОстатка = РазобратьОстатокБилета(ОстатокСтроки, Шаблоны);
ЗаполнитьЗначенияСвойств(ДанныеБилета, ДанныеОстатка);
Возврат ДанныеБилета;
КонецФункции
// --- ШАГ 1: ТИП БИЛЕТА ---
Функция ИзвлечьТипБилета(ОстатокСтроки, ШаблонТип)
ТипБилета = "";
РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонТип);
Если РезультатПоиска <> Неопределено Тогда
Блок = РезультатПоиска.Значение;
ТипБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонТип, "$1"));
ОстатокСтроки = СокрЛП(Сред(ОстатокСтроки, РезультатПоиска.Длина + 1));
КонецЕсли;
Возврат ТипБилета;
КонецФункции
// --- ШАГ 2: ПЕРЕВОЗЧИК И ИНН ---
Функция ИзвлечьПеревозчикаИИнн(ОстатокСтроки, ШаблонПеревозчик)
Результат = Новый Структура("Перевозчик, ИНН", "", "");
РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонПеревозчик);
Если РезультатПоиска <> Неопределено Тогда
Блок = РезультатПоиска.Значение;
Результат.Перевозчик = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонПеревозчик, "$1"));
ТекстИНН = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонПеревозчик, "$2"));
Результат.ИНН = СтрЗаменить(ТекстИНН, "$2", "");
ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Блок, ""));
КонецЕсли;
Возврат Результат;
КонецФункции
// --- ШАГ 3: КЛАСС ОБСЛУЖИВАНИЯ ---
Функция ИзвлечьКлассБилета(ОстатокСтроки, ШаблонКласс)
КлассБилета = "";
РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонКласс);
Если РезультатПоиска <> Неопределено Тогда
Блок = РезультатПоиска.Значение;
КлассБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонКласс, "$1"));
ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Блок, ""));
КонецЕсли;
Возврат КлассБилета;
КонецФункции
// --- ШАГ 4 и 5: ДАТА, НОМЕР, МАРШРУТ, ФИО ---
Функция РазобратьОстатокБилета(Знач ОстатокСтроки, Шаблоны)
Результат = Новый Структура("Дата, Пассажир, ДопИнфо, НомерБилета, Маршрут", "", "", "", "", "");
// Очищаем мусор перед номерами (№, Квитанция и т.д.)
ОстатокСтроки = СтрЗаменитьПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.МусорСлеш, "/ ");
ОстатокСтроки = СтрЗаменитьПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.МусорУдалить, "");
ОстатокСтроки = СокрЛП(ОстатокСтроки);
РезультатПоискаДата = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.Дата);
Если РезультатПоискаДата <> Неопределено Тогда
// ------------------ БИЛЕТ С ДАТОЙ ------------------
Результат.Дата = РезультатПоискаДата.Значение;
// Разбиваем строку на две части (до даты и после)
ПозицияДаты = СтрНайти(ОстатокСтроки, Результат.Дата);
Хвост = СокрЛП(Сред(ОстатокСтроки, ПозицияДаты + СтрДлина(Результат.Дата)));
СтрокаНомерМаршрут = СокрЛП(Лев(ОстатокСтроки, ПозицияДаты - 1));
// Разбор хвоста на ФИО и ДопИнфо
ПозЗапятой = СтрНайти(Хвост, ",");
Если ПозЗапятой > 0 Тогда
Результат.Пассажир = СокрЛП(Лев(Хвост, ПозЗапятой - 1));
Результат.ДопИнфо = СокрЛП(Сред(Хвост, ПозЗапятой + 1));
Иначе
Результат.Пассажир = Хвост;
КонецЕсли;
// Разбор начала на Номер и Маршрут
РезультатПоискаНМ = СтрНайтиПоРегулярномуВыражению(СтрокаНомерМаршрут, Шаблоны.НомерМаршрут);
Если РезультатПоискаНМ <> Неопределено Тогда
Блок = РезультатПоискаНМ.Значение;
Результат.НомерБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.НомерМаршрут, "$1"));
ТекстМаршрута = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.НомерМаршрут, "$2"));
Результат.Маршрут = СтрЗаменить(ТекстМаршрута, "$2", "");
Иначе
Результат.НомерБилета = СтрокаНомерМаршрут;
КонецЕсли;
Иначе
// ------------------ БИЛЕТ БЕЗ ДАТЫ ------------------
РезультатПоискаБездатный = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.Бездатный);
Если РезультатПоискаБездатный <> Неопределено Тогда
Блок = РезультатПоискаБездатный.Значение;
Результат.НомерБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$1"));
ТекстМаршрута = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$2"));
Результат.Маршрут = СтрЗаменить(ТекстМаршрута, "$2", "");
ТекстПассажира = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$3"));
Результат.Пассажир = СтрЗаменить(ТекстПассажира, "$3", "");
Иначе
// На случай, если строка вообще нестандартная
Результат.НомерБилета = ОстатокСтроки;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции