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를 반드시 수행 할 필요는 없습니다.
답변
당신은 이것을 필요 patch
로 하지 않습니다 ; 변경 사항을 추출하여 파일의 변경되지 않은 부분으로 전송하기위한 것입니다.
두 버전의 파일을 병합하는 도구는 merge
이지만 @vonbrand
, 기록한 것처럼 두 버전이 서로 다른 “기본”파일이 필요합니다. 병합하지 않고 병합하려면 다음 diff
과 같이 사용 하십시오.
diff -DVERSION1 file1.xml file2.xml > merged.xml
다음과 같이 C 스타일 #ifdef
/ #ifndef
“전 처리기”명령 에서 각 변경 사항을 묶습니다 .
#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
. 설명서를 읽으십시오).
답변
merge(1)
아마 당신이 원하는 것에 더 가깝지만 두 파일의 공통 조상이 필요합니다.
그것을하는 (더러운!) 방법은 다음과 같습니다.
- 첫 번째 줄과 마지막 줄
grep(1)
을 제거하고 사용 하여 제외하십시오. - 결과를 함께 스매시
sort -u
정렬 된 목록을 남기고 중복을 제거합니다.- 첫 번째 / 마지막 줄 바꾸기
흠 … 선을 따라 뭔가 :
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'
할 수 있습니다.
답변
sdiff
(1)-파일 차이를 나란히 병합
이 --output
옵션을 사용하면 두 파일을 대화식으로 병합합니다. 간단한 명령 을 사용 하여 변경을 선택하거나 변경을 편집합니다.
EDITOR
환경 변수가 설정되어 있는지 확인해야합니다 . “eb”와 같은 명령의 기본 편집기는 일반적으로 ed
라인 편집기 입니다.
EDITOR=nano sdiff -o merged.txt file1.txt file2.txt
답변
최대 10 개의 파일을 병합 하는 간단한 솔루션은 다음과 같습니다 .
#!/bin/bash
strip(){
i=0
for f; do
sed -r '
/<\/?resources>/ d
s/>/>'$((i++))'/
' "$f"
done
}
strip "$@" | sort -u -k1,1 -t'>' | sed '
1 s|^|<resources>\n|
s/>[0-9]/>/
$ a </resources>
'
먼저 오는 인수가 우선권을 가지 므로 다음을 호출해야합니다.
script b.xml a.xml
b.xml
대신 공통 값을 유지 a.xml
합니다.
script b.xml a.xml
야당:
<resources>
<color name="in_b_but_different_val">#BBBBBB</color>
<color name="not_in_a">#AAAAAA</color>
<color name="not_in_b">#AAAAAA</color>
<color name="not_in_b_too">#AAAAAA</color>
<color name="same_in_b">#AAABBB</color>
</resources>
답변
또 다른 끔찍한 해킹-단순화 할 수는 있지만 : 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>"
답변
좋아, 두 번째 시도, 이제 Perl에서 ( 생산 품질이 아니라 검사하지 않음) :
#!/usr/bin/perl
open(A, "a.xml");
while(<A>) {
next if(m;^\<resource\>$;);
next if(m;^\<\/resource\>$;);
($name, $value) = m;^\s*\<color\s+name\s*\=\s*\"([^"]+)\"\>([^<]+)\<\/color\>$;;
$nv{$name} = $value if $name;
}
close(A);
open(B, "b.xml");
while(<B>) {
next if(m;^\<resource\>$;);
next if(m;^\<\/resource\>$;);
($name, $value) = m;^\s*\<color\s+name\s*\=\*\"([^"]+)\"\>([^<]+)\<\/color\>$;;
$nv{$name} = $value if $name;
}
close(B);
print "<resource>\n";
foreach (keys(%nv)) {
print " <color name=\"$_\">$nv{$_}</color>\n";
}
print "</resource>\n";
답변
cut과 grep을 사용하는 또 다른 방법은 … (a.xml b.xml을 인수로 사용함)
#!/bin/bash
zap='"('"`grep '<color' "$2" | cut -d '"' -f 2 | tr '\n' '|'`"'")'
echo "<resources>"
grep '<color' "$1" | grep -E -v "$zap"
grep '<color' "$2"
echo "</resources>"