Compare linhas e atualize dois arquivos diferentes

3

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?

    
por BowPark 01.06.2016 / 13:39

2 respostas

0

diff file_1 file_2 | grep -Ev '^<|[0-9]+d[0-9]+' | patch file_1
    
por 02.06.2016 / 11:14
0

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.

    
por 02.06.2016 / 14:25