Я читал о diff и patch, но не могу понять, как применить то, что мне нужно. Я думаю, это довольно просто, поэтому, чтобы показать мою проблему, возьмите эти два файла:
a.xml
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="not_in_b">#AAAAAA</color>
<color name="in_b_but_different_val">#AAAAAA</color>
<color name="not_in_b_too">#AAAAAA</color>
</resources>
b.xml
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="in_b_but_different_val">#BBBBBB</color>
<color name="not_in_a">#AAAAAA</color>
</resources>
Я хочу получить вывод, который выглядит следующим образом (порядок не имеет значения):
<resources>
<color name="same_in_b">#AAABBB</color>
<color name="not_in_b">#AAAAAA</color>
<color name="in_b_but_different_val">#BBBBBB</color>
<color name="not_in_b_too">#AAAAAA</color>
<color name="not_in_a">#AAAAAA</color>
</resources>
Слияние должно содержать все строки по этим простым правилам:
- любая строка, которая есть только в одном из файлов
- если строка имеет тот же тег имени, но другое значение, возьмите значение из второго
Я хочу применить эту задачу в скрипте bash, поэтому она не обязательно должна быть завершена с помощью diff и patch, если другая программа лучше подходит
diff
может сказать вам, какие строки находятся в одном файле, но не в другом, но только по степени детализации целых строк.patch
подходит только для внесения одинаковых изменений в аналогичный файл (возможно, в другую версию того же файла или в совершенно другой файл, где, однако, номера строк и окружающие строки для каждого изменения идентичны вашему исходному файлу). Так что нет, они не особенно подходят для этой задачи. Возможно, вы захотите взглянуть,wdiff
но решение, вероятно, требует специального сценария. Поскольку ваши данные выглядят как XML, вам может понадобиться какой-нибудь инструмент XSL.Ответы:
Вам не нужно
patch
для этого; это для извлечения изменений и отправки их без неизменной части файла.Инструмент для слияния двух версий файла есть
merge
, но, как@vonbrand
написали, вам нужен «базовый» файл, из которого ваши две версии расходятся. Чтобы сделать слияние без него, используйтеdiff
так:Он будет включать в себя каждый набор изменений в командах в стиле C
#ifdef
/#ifndef
«препроцессор», например:Если линия или область отличаются между двумя файлами, вы получите «конфликт», который выглядит следующим образом:
Поэтому сохраните вывод в файл и откройте его в редакторе. Ищите любые места, где
#else
выплывает, и разрешайте их вручную. Затем сохраните файл и запустите его,grep -v
чтобы избавиться от оставшихся строк#if(n)def
и#endif
строк:В дальнейшем сохраните оригинальную версию файла.
merge
может дать вам гораздо лучшие результаты с помощью дополнительной информации. (Но будьте осторожны:merge
редактируйте один из файлов на месте, если вы не используете-p
. Прочтите руководство).источник
sed -e "s/^#else.*$/\/\/ conflict/g"
#else
строки вручную в редакторе во время разрешения конфликта.merge(1)
вероятно, ближе к тому, что вы хотите, но это требует общего предка ваших двух файлов.(Грязный!) Способ сделать это:
grep(1)
для их исключенияsort -u
оставляет отсортированный список, удаляет дубликатыХм ... что-то вроде:
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'
может сделать.
источник
name
in_b_but_different_val
имеет значение#00AABB
sort, оно помещает его сверху и удаляет второе значение вместо первогоdiff3
работает так же. Требуется файл общего предка. Почему нет простого инструмента CLI, который просто объединяет 2 файла в зависимости от того, чтоdiff
показывает.sdiff
(1) - параллельное объединение различий в файлахИспользуйте
--output
опцию, это интерактивно объединит любые два файла. Вы используете простые команды, чтобы выбрать изменение или отредактировать изменение.Вы должны убедиться, что
EDITOR
переменная окружения установлена. Редактором по умолчанию для таких команд, как «eb», обычноed
является редактор строк .источник
vim
в качестве редактора как лучше. Но это лучшее решение, оно приходит и сdiff
командой!Вот простое решение, которое работает, объединяя до 10 файлов :
обратите внимание, что аргумент, который стоит первым, имеет приоритет, поэтому вам нужно позвонить:
чтобы получить общие ценности,
b.xml
а неa.xml
.script b.xml a.xml
выходы:источник
Еще один ужасный взлом - можно упростить, но: P
источник
Хорошо, вторая попытка, теперь в Perl ( не качество продукции, не проверка!):
источник
Еще один, используя cut и grep ... (принимает a.xml b.xml в качестве аргументов)
источник
echo
является действием по умолчанию, поэтомуxargs echo
является излишним. Почему бы тебе просто неtr '\n' '|'
пойти?