差分とパッチについて読みましたが、必要なものを適用する方法がわかりません。私はそれがかなり単純だと思いますので、私の問題を示すためにこれらの2つのファイルを取ります:
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
は必要ありません。変更を抽出して、ファイルの変更されていない部分なしで送信するためのものです。
ファイルの2つのバージョンをマージするためのツールはmerge
ですが、_@vonbrand
_が書いたように、2つのバージョンが分岐した「ベース」ファイルが必要です。それなしでマージを行うには、次のように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
_
2つのファイル間でラインまたはリージョンが異なる場合、次のような「競合」が発生します。
_#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
は、追加情報の助けを借りて、より良い結果を与えることができます。 (ただし注意してください:_-p
_を使用しない限り、merge
はファイルの1つを編集します。マニュアルをお読みください)。
merge(1)
は、おそらくあなたが望むものに近いでしょうが、そのためには2つのファイルの共通の祖先が必要です。
(汚い!)それを行う方法は:
grep(1)
を使用してそれらを除外しますsort -u
ソートされたリストを残し、重複を排除しますうーん...線に沿って何か:
echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'
行う可能性があります。
ここで動作する簡単なソリューション最大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>"
OK、2回目の試行、Perlで(not製品の品質、チェックなし!):
#!/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";
もう1つは、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>"