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 n
umber the l
ines in conf1
and conf2
and sort
them by 2
nd 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...
last
isstar
and not''
)? – Stéphane Chazelas May 28 at 10:46diff
is designed for? – CousinCocaine May 28 at 19:15