Понадобилось мне 2 строки сравнить и определить, какие в них фрагменты совпадают, а какие различаются. Для удобства привёл строки к одной длине. Впрочем, при желании любые 2 строки можно порубать так, чтобы сравнивать как имеющие одинаковую длину. Ну и ничего, кроме хитрых регулярных выражений да посимвольного перебора не нашёл. RegExp не удалось припахать к выдаче результата в нужном мне виде (возможно, мои руки кривы), а посимвольно обходить длинные строки не хотелось. В итоге сделал эту, авось кому пригодится.
Функция ПолучитьРазличияДвухСтрок(Знач стро1,Знач стро2,тф=Неопределено,Знач рДельта=0)
Если тф=Неопределено Тогда
// это первая итерация, инициализируемся
рМаксДлина=0;
// результаты вернём в таблице значений, фиксирующей фрагменты: № начсим, № консим, ЕстьРазница (булево)
тф=Новый ТаблицаЗначений;
тф.Колонки.Добавить("Начало");
тф.Колонки.Добавить("Конец");
тф.Колонки.Добавить("ЕстьРазница");
Если стро1=стро2 Тогда // разницы вообще нет
стротф=тф.Добавить();
стротф.Начало=1;
стротф.Конец=СтрДлина(стро2);
Возврат тф;
Иначе
рДлина1=СтрДлина(стро1);
рДлина2=СтрДлина(стро2);
Если рДлина1<>рДлина2 Тогда // можно обрезать под одну длину, можно и отказаться
рМинДлина=Мин(рДлина1,рДлина2);
рМаксДлина=Макс(рДлина1,рДлина2);
Если рМинДлина=рДлина1 Тогда стро2=Лев(стро2,рМинДлина) КонецЕсли;
Если рМинДлина=рДлина2 Тогда стро1=Лев(стро1,рМинДлина) КонецЕсли;
КонецЕсли;
КонецЕсли;
// заполним дихотомически
ПолучитьРазличияДвухСтрок(стро1,стро2,тф);
// дообработаем разницу длин, если она была, дописав "хвост" более длинной строки
Если рМаксДлина<>0 Тогда
стротф=тф.Добавить();
стротф.Начало=рМинДлина+1;
стротф.Конец=рМаксДлина;
стротф.ЕстьРазница=Истина; // априорно
КонецЕсли;
// грубо свернём (такая таблица никогда не будет очень большой, поэтому можно не изощряться)
тф2=тф.СкопироватьКолонки(); старЕР=Неопределено; старНачало=0; старКонец=0;
Для каждого стротф Из тф Цикл
Если старЕР<>стротф.ЕстьРазница Тогда
Если старЕР<>Неопределено Тогда // закончим предыдущую
стротф2=тф2.Добавить();
стротф2.Начало=старНачало;
стротф2.Конец=старКонец;
стротф2.ЕстьРазница=старЕР;
КонецЕсли;
старЕР=стротф.ЕстьРазница;
старНачало=стротф.Начало;
КонецЕсли;
старКонец=стротф.Конец;
КонецЦикла;
Если старЕР<>Неопределено Тогда // закончим предыдущую
стротф2=тф2.Добавить();
стротф2.Начало=старНачало;
стротф2.Конец=старКонец;
стротф2.ЕстьРазница=старЕР;
КонецЕсли;
Возврат тф2;
Иначе
// собственно рекурсивное сравнение строк
этстро=стро1; // строка-эталон
обрстро=стро2; // обрабатываемая строка
пози=Цел(СтрДлина(обрстро)/2);
Если пози=0 Тогда Возврат "" КонецЕсли; // ненормальная ситуация
кусэт1=Лев(этстро,пози);
кусэт2=Сред(этстро,пози+1);
кусобр1=Лев(обрстро,пози);
кусобр2=Сред(обрстро,пози+1);
изм1=(кусэт1<>кусобр1);
изм2=(кусэт2<>кусобр2);
// смотрим первый кусок
Если не изм1 Тогда
стротф=тф.Добавить();
стротф.Начало=?(рДельта=0,1,рДельта);
стротф.Конец=стротф.Начало+СтрДлина(кусобр1)-1;
стротф.ЕстьРазница=Ложь;
Иначе // эта часть различна, идём дальше, обрабатывая её как отдельную строку
рНачало=?(рДельта=0,1,рДельта);
рКонец=рНачало+СтрДлина(кусобр1)-1;
Если рНачало=рКонец Тогда // финальная фаза, 1 символ разницы
стротф=тф.Добавить();
стротф.Начало=рНачало;
стротф.Конец=рКонец;
стротф.ЕстьРазница=Истина;
Иначе
ПолучитьРазличияДвухСтрок(кусэт1,кусобр1,тф,рДельта);
КонецЕсли;
КонецЕсли;
// смотрим второй кусок
рДельта=(пози+1)+рДельта-?(рДельта=0,0,1);
Если не изм2 Тогда
стротф=тф.Добавить();
стротф.Начало=рДельта;
стротф.Конец=стротф.Начало+СтрДлина(кусобр2)-1;
стротф.ЕстьРазница=Ложь;
Иначе // эта часть различна, идём дальше, обрабатывая её как отдельную строку
рНачало=рДельта;
рКонец=рНачало+СтрДлина(кусобр2)-1;
Если рНачало=рКонец Тогда // финальная фаза, 1 символ разницы
стротф=тф.Добавить();
стротф.Начало=рНачало;
стротф.Конец=рКонец;
стротф.ЕстьРазница=Истина;
Иначе
ПолучитьРазличияДвухСтрок(кусэт2,кусобр2,тф,рДельта);
КонецЕсли;
КонецЕсли;
// ничего не возвращаем, результат не важен
КонецЕсли;
КонецФункции
Пример вызова:
тф=ПолучитьРазличияДвухСтрок(строка1,строка2);