LINUX.ORG.RU

Игнорировать разрывы строк при сравнении текстовых файлов

 ,


0

1

Есть 9-мегабайтный текстовый файл. Я в него добавил в разные места несколько килобайт, затем неправильно применил в FAR-е скрипт EditWrap.lua и по ошибке сохранил. Бэкап, сделанный до всех правок, есть.

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

a bc d

и

a b
c d

Если при этом фрагменты окажутся одинаковыми с a b c d или abcd — значения не имеет, не проблема.

diff, насколько я понял, может приравнять любое число пробелов и табов к одному пробелу, но игнорировать разрыв строки не может.

wdiff и dwdiff работают на уровне слов, поэтому разрывы строк, разрывающие слова, они игнорировать не смогут. Так?

Что ещё есть?

UPD: Сравнил их скриптом на Питоне в полуручном режиме, но вопрос о более универсальном решении остался.

★★★★★

Последнее исправление: question4 (всего исправлений: 2)
Ответ на: комментарий от ALiEN175

Вообще поубирать переносы и сравнить?

В смысле? Вручную убрать 29 000 переносов? Или весь файл в одну строку? Тогда как сравнивать и переносить изменения в многострочный файл?

question4 ★★★★★
() автор топика

В общем, задачу решил на питоне, но вопрос остаётся.

Скрипт, если кому интересно:

def eq_lim_len(q4, q6):
    return q4[:len(q6)] == q6

def eq_assemble(p4, p6):
    if '' == q4[p4] == q6[p6]:
        return 1
    attempt = 0
    while p6 + attempt < len(q6) and q6[p6 + attempt] != '' and eq_lim_len(q4[p4], ''.join(q6[ p6 : p6 + attempt + 1 ]) ):
        attempt += 1
    return attempt

q4 = open('q4.txt', 'rt').read().split('\n')
q6 = open('q6.txt', 'rt').read().split('\n')

p6 = 0
for p4 in range(len(q4)):
    r = eq_assemble(p4, p6)
    if r > 0:
        p6 += r
    if r == 0:
        print(p4, p6, '\n', q4[p4-2:p4+2], '\n', q6[p6-2:p6+3])
        break

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

question4 ★★★★★
() автор топика

UPD: Сравнил их скриптом на Питоне в полуручном режиме, но вопрос о более универсальном решении остался.

Я по итогам аналогичных задач пришёл к выводу, что скрипт на Питоне (в моём случае на Перле) и есть самое универсальное решение. Можно ещё awk поковырять, коим я не владею.

Мне, например, иногда не хватает многострочной замены в sed, если бы она была – множества велосипедов удалось бы избежать.

hobbit ★★★★★
()
Ответ на: комментарий от kaldeon

https://man.archlinux.org/man/core/diffutils/cmp.1

Каким образом синхронизировать файлы после сдвигов от добавленных разрывов?

question4 ★★★★★
() автор топика
Последнее исправление: question4 (всего исправлений: 1)
Ответ на: комментарий от hobbit

что скрипт на Питоне (в моём случае на Перле) и есть самое универсальное решение

Каким образом в скрипте сделать синхронизацию после различающихся фрагментов? Большая часть добавляемых строк — в q6, но в q4 было несколько строк, которые в q6 оказались далеко передвинуты. То есть возможны случаи, когда строка из q4 не имеет соответствий в q6, но гораздо чаще строка из q6 не имеет соответствий в q4.

question4 ★★★★★
() автор топика
Ответ на: комментарий от flant

sed ':a;N;$!ba; ... файл

Как-то я пытался так работать с файлом то ли 1,7 то ли 3,7 мегабайта. Удалял из «Гаргантюа и Пантагрюэля» мусор, который в HTML насовала Bestlibrary(?), деталей не помню. sed отъел кучу памяти и завис.

question4 ★★★★★
() автор топика

перенести отличия из нового в старый

Правильно ли я понял, что сравнить файлы нужно без разрывов строк (таб, пробел, \n), а отличия, исключая эти самые разрывы, нужно перенести?

Пример:

foobarbazqux
foo
barlol
kekbazqux

Нужно перенести lol\nkek в foobarbazqux между bar и baz, получая:

foobarlol
kekbazqux
kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 1)
Ответ на: комментарий от kaldeon

Пример:

Бэкап:

строка1строка2
строка3строка4
строка5
строка6
строка7
строка8

Новый:

строка1строка2
строка9
строка3строка4
строка5
строка6
строка8

Повреждённый:

строка1
строка2
строка9
строка3
строка4
строка5
строка6
строка8

Сравниваются бэкап и повреждённый. Требуется результат в виде, в каком его показывает diff: «вставить ‘строка9’ между строками 1 и 2, удалить строку 5».

question4 ★★★★★
() автор топика
Последнее исправление: question4 (всего исправлений: 1)