我已阅读有关 diff 和 patch 的内容,但我不知道如何应用我需要的内容。我想它非常简单,所以为了展示我的问题,请使用这两个文件:
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 来完成
答案1
你不需要patch
这个;它用于提取更改并发送它们,而无需文件中未更改的部分。
用于合并文件的两个版本的工具是merge
,但正如@vonbrand
所写,您需要两个版本分歧的“基本”文件。要在没有它的情况下进行合并,请diff
像这样使用:
diff -DVERSION1 file1.xml file2.xml > merged.xml
#ifdef
它将包含 C 风格/ “预处理器”命令中的每组更改#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
。请阅读手册)。
答案2
答案3
merge(1)
可能更接近您想要的,但这需要两个文件有一个共同的祖先。
一种(肮脏的!)方法是:
- 去掉第一行和最后一行,使用
grep(1)
排除它们 - 将结果粉碎在一起
sort -u
留下排序列表,消除重复项- 替换第一行/最后一行
嗯……大概是这样的:
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>"