You could use join to merge the two files and preserve the order of the keys. Here's an example:
conf1:
name='john'
last=''
custom='1000'
rule='default'
conf2:
name='joe'
second='none'
fourth='dash'
last='star'
rule='whatever'
if you run:
{ { join -t= -1 2 -2 1 -o 1.1 1.2 2.2 <(sort -t= -k2,2 <(nl -ba -nrz -s= conf1)) \
<(sort -t= -k1,1 conf2); join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 \
<(sort -t= -k2,2 <(nl -ba -nrz -s= conf1)) <(sort -t= -k1,1 conf2); \
} | sort -k1,1n | cut -d= -f2-; join -t= -1 1 -2 2 -v2 -o 2.1 2.2 2.3 \
<(sort -t= -k1,1 conf1) <(sort -t= -k2,2 <(nl -ba -nrz -s= conf2)) \
| sort -k1,1n | cut -d= -f2-; } > merged_conf
the content of merged_conf is:
name='joe'
last='star'
custom='1000'
rule='whatever'
second='none'
fourth='dash'
Maybe it's easier to understand if working with two temporary files. First number the lines in conf1 and conf2 and sort them by 2nd field:
sort -t= -k2,2 <(nl -ba -nrz -s= conf1) >conf1.sorted
sort -t= -k2,2 <(nl -ba -nrz -s= conf2) >conf2.sorted
the above creates conf1.sorted:
000003=custom='1000'
000002=last=''
000001=name='john'
000004=rule='default'
and conf2.sorted:
000003=fourth='dash'
000004=last='star'
000001=name='joe'
000005=rule='whatever'
000002=second='none'
Now, the same command using the original files and the numbered/sorted files:
{ { join -t= -1 2 -2 1 -o 1.1 1.2 2.2 conf1.sorted <(sort -t= -k1,1 conf2); \
join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 conf1.sorted \
<(sort -t= -k1,1 conf2); } | sort -k1,1n | cut -d= -f2-; \
join -t= -1 1 -2 2 -v2 -o 2.1 2.2 2.3 <(sort -t= -k1,1 conf1) conf2.sorted \
| sort -k1,1n | cut -d= -f2-; } > merged_conf
Explanation:
join -t= -1 2 -2 1 -o 1.1 1.2 2.2 conf1.sorted <(sort -t= -k1,1 conf2)
joins the files based on field 2 from conf1.sorted and field 1 from conf2 printing the common lines but with the values (2.2) from conf2:
000002=last='star'
000001=name='joe'
000004=rule='whatever
and
join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 conf1.sorted <(sort -t= -k1,1 conf2)
prints the unpairable lines from conf1.sorted:
000003=custom='1000'
they're grouped {..} and the output is piped to sort -k1,1n | cut -d= -f2- so as to restore the order of keys from the original conf1:
name='joe'
last='star'
custom='1000'
rule='whatever'
then
join -t= -1 1 -2 2 -v2 -o 2.1 2.2 2.3 <(sort -t= -k1,1 conf1) conf2.sorted
joins based on field 1 from conf1 and field 2 from conf2.sorted printing unpairable lines from the latter:
000003=fourth='dash'
000002=second='none'
in the same manner, the output is piped to sort -k1,1n | cut -d= -f2- so as to restore the order of keys from the original conf2:
second='none'
fourth='dash'
Grouping all the above produces the desired output:
name='joe'
last='star'
custom='1000'
rule='whatever'
second='none'
fourth='dash'
this is then redirected (>) to merged_conf. Finally, remove the sorted files:
rm conf{1,2}.sorted
This could then be repeated for additional config files using merged_conf and e.g conf3 as arguments and so on...
lastisstarand not'')?diffis designed for?