diff file_1 file_2 | grep -Ev '^<|[0-9]+d[0-9]+' | patch file_1
Eu tenho alguns arquivos de texto com os seguintes recursos:
$ cat file_1
Line A
Line B
Line C
Line D
$ cat file_2
Line A
Line added 1
Line B
Line D
Line added 2
Eles são tais que file_1
tem algumas linhas que file_2
não contém e vice-versa. Eu gostaria de atualizar uns aos outros com as linhas que faltam para que ambos se tornem
Line A
Line added 1
Line B
Line C
Line D
Line added 2
A ordem de file_1
é preservada, mas com as integrações provenientes de file_2
colocadas nos mesmos lugares que em file_2
(não na cabeça ou na cauda ou aleatoriamente posições).
1) É possível mesclar os arquivos através de um script bash
apropriado?
2) É possível fazer o mesmo, quando em vez de linhas eu tenho parágrafos, isto é: blocos de linhas?
diff file_1 file_2 | grep -Ev '^<|[0-9]+d[0-9]+' | patch file_1
1) Is this possible to merge this way the files through an appropriate bash script?
Como outros comentaristas disseram, separar adicionar / mover / excluir não é preciso, e é melhor deixar para diff
. Mas com a restrição de que as linhas "originais" são únicas e aparecem na mesma ordem em ambos os arquivos, é mais simples:
#!/bin/bash
#build list of common lines
grep -Fxf file_2 file_1 > common
#optional: confirm that they appear in the same order in both files
grep -Fxf file_1 file_2 > common2
if ! diff -q common common2 ; then
echo "Duplicate or rearranged common lines, can't merge" >&2
exit 1
fi
#copy lines from input until one is found that matches the argument
function copy_till () {
while read l && [ "$l" != "$1" ] ; do
printf "%s\n" "$l"
done
}
# open both files, for parallel reading
exec 3< file_1
exec 4< file_2
#for each line in the common file
while read line ; do
# copy any lines that were inserted before it, for each input file
copy_till "$line" <&3
copy_till "$line" <&4
# and the original line
printf "%s\n" "$line"
done < common > merged
# any trailing lines, after the last common line
cat <&3 >> merged
cat <&4 >> merged
2) Is it possible to do the same, when instead of lines I have paragraphs, that is: blocks of lines?
Depois de ter uma maneira de fazer isso para linhas, você pode usar sed
para transformar parágrafos em linhas longas (salvando as novas linhas como outro token temporário) e voltar. Emprestando strongmente o script anotado no link :
sed '/^$/!{H;$ba;d};:a;x;s/\n/\n/gp;d' -i.bak file_1
sed '/^$/!{H;$ba;d};:a;x;s/\n/\n/gp;d' -i.bak file_2
merge.sh # or whatever you called the answer to part 1)
sed 's/\n/\n/g' merged > merged.paras
mv file_1.bak file_1
mv file_2.bak file_2
Se a string \n
aparecer nos seus parágrafos, use outra string como o token de nova linha.