diff cada linha individual no primeiro arquivo contra todas as linhas no segundo arquivo?

2

Eu tenho 2 representações TCL de um projeto que são geradas por duas versões diferentes da mesma ferramenta, vamos chamá-las de v1.tcl e v2.tcl

Esses logs são logicamente idênticos para todos os efeitos, com exceção da ordem das linhas. Cada linha em v1.tcl será encontrada em algum lugar exatamente uma vez em v2.tcl quando as versões 1 e 2 do meu projeto forem idênticas.

Gostaria de poder identificar se alguém fez uma alteração em v2.tcl que precisa ser backportada para v1.tcl (ou vice-versa) ... em outras palavras, gostaria de ver apenas as linhas em que não correspondem. Por exemplo:

  1. v1.tcl :

    foo1
    bar1
    hello1
    world1
    
  2. v2.tcl :

    hello1
    bar1
    foo2
    world1
    goodbye2
    
  3. valor de retorno "diff":

    file1:1 foo1
    file2:3 foo2
    file2:5 goodbye2
    

Eu deveria escrever meu próprio roteiro? Existe uma ferramenta que já faz isso?

    
por IDLacrosseplayer 27.09.2018 / 05:46

1 resposta

5

Se as linhas forem idênticas e você só quiser saber se houver linhas extras em um arquivo ou outro, você poderá usar o tipo & diff (e substituição de processo aqui):

$ diff -B <(sort v1.tcl) <(sort v2.tcl)
2c2,3
< foo1
---
> foo2
> goodbye2

Com o -B do diff para ignorar linhas em branco. Você pode usar grep -n [pattern] file para descobrir em qual linha o padrão está (talvez com uma ou uma combinação de grep , cut , sed , awk ), se isso for importante.

Aqui está uma resposta mais completa, mostrando o arquivo e o número da linha contendo correspondências. Não usa sed ou awk, apenas bash, cut, grep ... aqui está tudo (essencialmente) em uma linha:

diff -B <(sort v1.tcl) <(sort v2.tcl) | while read -r line; do if \
echo "$line" | grep -q "^<"; then grep -F -n -H \
"$(echo "$line"|cut -c3-)" v1.tcl ; elif echo "$line" | grep -q \
"^>"; then grep -F -n -H "$(echo "$line"|cut -c3-)" v2.tcl ; fi done

Ou dividido em várias linhas:

diff -B <(sort v1.tcl) <(sort v2.tcl) | while read -r line
do
  if echo "$line" | grep -q "^<"
    then grep -F -n -H "$(echo "$line"|cut -c3-)" v1.tcl
  elif echo "$line" | grep -q "^>"
    then grep -F -n -H  "$(echo "$line"|cut -c3-)" v2.tcl
  fi
done

E, dependendo dos seus arquivos de entrada (especialmente se você tiver linhas com barras invertidas), estou usando essas opções para ler & grep:

  • read -r não permite que barras invertidas escapem de qualquer caractere
  • grep -F Interprete PATTERN como uma lista de sequências fixas (em vez de expressões regulares), separadas por novas linhas, as quais devem ser correspondidas

Além disso, usando comentários do Pimp Juice IT , se houver barras invertidas para linhas nos arquivos de entrada grep fornece o erro "file: line Trailing backslash". Usar a opção -F para que o grep limpe o erro de barra invertida no final resulta em uma solução somente menor do grep:

grep -FvHn -f v2.tcl v1.tcl ;grep -FvHn -f v1.tcl v2.tcl

opções do grep usadas:

  • -f Obtém padrões de FILE, um por linha.
  • -F Interprete PATTERN como uma lista de sequências fixas (em vez de expressões regulares), separadas por novas linhas, as quais devem ser correspondidas
  • -v Inverte o sentido de correspondência para selecionar linhas não correspondentes.
  • -H Imprime o nome do arquivo para cada correspondência
  • -n Prefixe cada linha de saída com o número de linha baseado em 1 em seu arquivo de entrada.
por 27.09.2018 / 06:18