patch와 diff를 사용하여 두 파일을 병합하고 자동으로 충돌을 해결하는 방법

patch와 diff를 사용하여 두 파일을 병합하고 자동으로 충돌을 해결하는 방법

차이점과 패치에 대해 읽었지만 필요한 것을 적용하는 방법을 모르겠습니다. 나는 그것이 매우 간단하길 원하므로 내 문제를 보여주기 위해 다음 두 파일을 사용하십시오.

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>

병합에는 다음과 같은 간단한 규칙을 따르는 모든 줄이 포함되어야 합니다.

  1. 파일의 모든 줄만
  2. 한 행에 동일한 이름 태그가 있지만 값이 다른 경우 두 번째 행에서 값을 가져옵니다.

이 작업을 bash 스크립트에 적용하고 싶기 때문에 다른 프로그램이 더 적합한 경우 diff 및 패치를 사용하여 반드시 수행할 필요는 없습니다.

답변1

이는 필요하지 않습니다 patch. 변경 사항을 추출하고 파일의 변경되지 않은 부분 없이 보내는 데 사용됩니다.

두 가지 버전의 파일을 병합하는 도구가 있지만 작성된 merge대로 @vonbrand두 버전을 분기하려면 "기본" 파일이 필요합니다. 없이 병합하려면 diff다음과 같이 사용하세요.

diff -DVERSION1 file1.xml file2.xml > merged.xml

#ifdef#ifndef여기에는 다음과 같은 C 스타일/"전처리기" 명령의 모든 변경 사항 세트가 포함됩니다 .

#ifdef VERSION1
<stuff added to file1.xml>
#endif
...
#ifndef VERSION1
<stuff added to file2.xml>
#endif

두 파일의 줄이나 영역이 다른 경우 다음과 같은 "충돌"이 발생합니다.

#ifndef VERSION1
<version 1>
#else /* VERSION1 */
<version 2>
#endif /* VERSION1 */

따라서 출력을 파일에 저장하고 편집기에서 엽니다. #else나타나는 모든 위치를 검색 하고 수동으로 해결하세요. 그런 다음 파일을 저장하고 실행하여 grep -v나머지 #if(n)def합계 #endif줄을 제거합니다.

grep -v '^#if' merged.xml | grep -v '^#endif' > clean.xml

앞으로는 원본 버전의 파일을 저장하시기 바랍니다. merge추가 정보가 있으면 더 나은 결과를 얻을 수 있습니다. (그러나 주의하십시오. merge를 사용하지 않는 한 이러한 파일 중 하나를 내부에서 편집하십시오 -p. 매뉴얼을 읽으십시오).

답변2

sdiff(1) - 파일 차이점을 나란히 병합

--output옵션을 사용하면 두 파일을 대화식으로 병합합니다. 당신은 간단하게 사용합니다주문하다변경 사항 또는 변경 사항 편집을 선택합니다.

EDITOR환경 변수가 설정되어 있는지 확인해야 합니다 . "eb"와 같은 명령의 기본 편집기는 일반적으로 다음과 같습니다.ed, 라인 편집기.

EDITOR=nano sdiff -o merged.txt file1.txt file2.txt

답변3

merge(1)아마도 원하는 것에 더 가깝지만 이를 위해서는 두 파일에 공통 조상이 있어야 합니다.

한 가지 (더러운!) 방법은 다음과 같습니다.

  1. 첫 번째 행과 마지막 행을 제거하려면 grep(1)다음을 사용하여 제외하세요.
  2. 결과를 하나로 묶어라
  3. sort -u정렬된 목록을 그대로 두고 중복 항목을 제거합니다.
  4. 첫 번째/마지막 줄 바꾸기

음... 아마 다음과 같을 겁니다:

echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'

그럴 수도 있겠네요.

답변4

또 다른 끔찍한 해킹은 단순화될 수 있습니다. :P

#!/bin/bash

i=0

while read line
do
    if [ "${line:0:13}" == '<color name="' ]
    then
        a_keys[$i]="${line:13}"
        a_keys[$i]="${a_keys[$i]%%\"*}"
        a_values[$i]="$line"
        i=$((i+1))
    fi
done < a.xml

i=0

while read line
do
    if [ "${line:0:13}" == '<color name="' ]
    then
        b_keys[$i]="${line:13}"
        b_keys[$i]="${b_keys[$i]%%\"*}"
        b_values[$i]="$line"
        i=$((i+1))
    fi
done < b.xml

echo "<resources>"

i=0

for akey in "${a_keys[@]}"
do
    print=1

    for bkey in "${b_keys[@]}"
    do
        if [ "$akey" == "$bkey" ]
        then
            print=0
            break
        fi
    done

    if [ $print == 1 ]
    then
        echo "  ${a_values[$i]}"
    fi

    i=$(($i+1))
done

for value in "${b_values[@]}"
do
    echo "  $value"
done

echo "</resources>"

관련 정보