diff dentro de uma linha

96

Eu tenho alguns despejos de sql que eu estou olhando as diferenças entre. diff pode obviamente me mostrar a diferença entre duas linhas, mas estou me deixando louca tentando descobrir quais valores na longa lista de valores separados por vírgula são aqueles que fazem com que as linhas sejam diferentes.

Qual ferramenta posso usar para apontar as diferenças de caracteres exatas entre duas linhas em certos arquivos?

    
por user394 12.04.2011 / 04:04

12 respostas

82

wdiff , a palavra diff para isso.

Na área de trabalho, o meld pode destacar as diferenças dentro de uma linha para você.

    
por 12.04.2011 / 07:46
23

Eu usei vimdiff para isso.

Aqui está uma captura de tela (não minha) mostrando diferenças de um ou dois caracteres menores que se destaca muito bem. Um tutorial rápido também .

    
por 12.04.2011 / 05:04
17

Apenas outro método usando o git-diff:

git diff -U0 --word-diff --no-index -- foo bar | grep -v ^@@

grep -v se não estiver interessado em posições dos diffs.

    
por 16.12.2016 / 11:24
6

Aqui está um método "..cabelo do cão que mordeu você" ...
diff chegou até você nesse ponto; use-o para ir mais longe ...

Aqui está a saída do uso dos pares de linhas de amostra ... indica uma TAB

Paris in the     spring 
Paris in the the spring 
             vvvv      ^

A ca t on a hot tin roof.
a cant on a hot  in roof 
║   v           ^       ^

the quikc brown box jupps ober the laze dogs 
The☻qui ckbrown fox jumps over the lazy dogs 
║  ║   ^ ║      ║     ║    ║          ║     ^

Aqui está o script .. Você só precisa descobrir os pares de linha de alguma forma .. (Eu usei diff apenas uma vez (duas vezes?) antes de hoje, então eu não sei suas muitas opções, e resolvendo o opções para este script foi o suficiente para mim, por um dia :) .. Eu acho que deve ser bastante simples, mas eu estou pronto para um coffee break ....

#
# Name: hair-of-the-diff
# Note: This script hasn't been extensively tested, so beware the alpha bug :) 
#   
# Brief: Uses 'diff' to identify the differences between two lines of text
#        $1 is a filename of a file which contains line pairs to be processed
#
#        If $1 is null "", then the sample pairs are processed (see below: Paris in the spring 
#          
# ║ = changed character
# ^ = exists if first line, but not in second 
# v = exists if second line, but not in first

bname="$(basename "$0")"
workd="/tmp/$USER/$bname"; [[ ! -d "$workd" ]] && mkdir -p "$workd"

# Use $1 as the input file-name, else use this Test-data
# Note: this test loop expands \t \n etc ...(my editor auto converts \t to spaces) 
if [[ "$1" == '' ]] ;then
  ifile="$workd/ifile"
{ while IFS= read -r line ;do echo -e "$line" ;done <<EOF
Paris in the spring 
Paris in the the spring
A cat on a hot tin roof.
a cant on a hot in roof
the quikc brown box jupps ober the laze dogs 
The\tquickbrown fox jumps over the lazy dogs
EOF
} >"$ifile"
else
  ifile="$1"
fi
#
[[ -f "$ifile" ]] || { echo "ERROR: Input file NOT found:" ;echo "$ifile" ;exit 1 ; }
#  
# Check for balanced pairs of lines
ilct=$(<"$ifile" wc -l)
((ilct%2==0)) || { echo "ERROR: Uneven number of lines ($ilct) in the input." ;exit 2 ; }
#
ifs="$IFS" ;IFS=$'\n' ;set -f
ix=0 ;left=0 ;right=1
while IFS= read -r line ;do
  pair[ix]="$line" ;((ix++))
  if ((ix%2==0)) ;then
    # Change \x20 to \x02 to simplify parsing diff's output,
    #+   then change \x02 back to \x20 for the final output. 
    # Change \x09 to \x01 to simplify parsing diff's output, 
    #+   then change \x01 into ☻ U+263B (BLACK SMILING FACE) 
    #+   to the keep the final display columns in line. 
    #+   '☻' is hopefully unique and obvious enough (otherwise change it) 
    diff --text -yt -W 19  \
         <(echo "${pair[0]}" |sed -e "s/\x09/\x01/g" -e "s/\x20/\x02/g" -e "s/\(.\)/\n/g") \
         <(echo "${pair[1]}" |sed -e "s/\x09/\x01/g" -e "s/\x20/\x02/g" -e "s/\(.\)/\n/g") \
     |sed -e "s/\x01/☻/g" -e "s/\x02/ /g" \
     |sed -e "s/^\(.\) *\x3C$/ \x3C  /g" \
     |sed -n "s/\(.\) *\(.\) \(.\)$//p" \
     >"$workd/out"
     # (gedit "$workd/out" &)
     <"$workd/out" sed -e "s/^\(.\)..$//" |tr -d '\n' ;echo
     <"$workd/out" sed -e "s/^..\(.\)$//" |tr -d '\n' ;echo
     <"$workd/out" sed -e "s/^.\(.\).$//" -e "s/|/║/" -e "s/</^/" -e "s/>/v/" |tr -d '\n' ;echo
    echo
    ((ix=0))
  fi
done <"$ifile"
IFS="$ifs" ;set +f
exit
#
    
por 12.04.2011 / 15:03
4

wdiff é, na verdade, um método muito antigo de comparar arquivos palavra por palavra. Funcionou reformatando arquivos, depois usando diff para encontrar diferenças e passá-las novamente. Eu mesmo sugeri adicionar contexto, de modo que, em vez de comparar palavra por palavra, ele faça isso com cada palavra cercada por outras palavras de "contexto". Isso permite que o diff se sincronize em passagens comuns em arquivos muito melhor, especialmente quando os arquivos são diferentes com apenas alguns blocos de palavras comuns. Por exemplo, ao comparar texto para plágio ou reutilização.

dwdiff foi criado posteriormente a partir de wdiff . Mas dwdiff usa essa função de reformatação de texto com bom efeito em dwfilter . Este é um ótimo desenvolvimento - significa que você pode reformatar um texto para corresponder a outro e, em seguida, compará-los usando qualquer visualizador gráfico de diferenças linha-a-linha. Por exemplo, usando-o com diff gráfico "difuso" ....

dwfilter file1 file2 diffuse -w

Isso reformata file1 para o formato de file2 e atribui isso a diffuse para uma comparação visual. file2 não está modificado, portanto você pode editar e mesclar diferenças de palavras diretamente em diffuse . Se você quiser editar file1 , você pode adicionar -r para reverter qual arquivo é reformatado. Experimente e você vai achar que é extremamente poderoso!

Minha preferência pelo diff gráfico (mostrado acima) é diffuse , pois parece muito mais limpo e útil. Também é um programa python autônomo, o que significa que é fácil de instalar e distribuir para outros sistemas UNIX.

Outros diffs gráficos parecem ter muitas dependências, mas também podem ser usados (você escolhe). Estes incluem kdiff3 ou xxdiff .

    
por 02.08.2016 / 02:32
3

Usando a solução do @Peter.O., como base, reescrevi-a para fazer uma série de alterações. p>

  • Eleimprimetodasaslinhasapenasumavez,usandocoresparamostrarasdiferenças.
  • Elenãogravanenhumarquivotemporário,canalizandotudoemseulugar.
  • Vocêpodefornecerdoisnomesdearquivosecompararaslinhascorrespondentesemcadaarquivo.%código%
  • Casocontrário,sevocêusaroformatooriginal(umúnicoarquivocomcadasegundalinhaprecisandosercomparadocomoanterior),vocêpodesimplesmenteinseri-lo,nãoénecessárioexistirnenhumarquivoparaserlido.Dêumaolhadaem./hairOfTheDiff.shfile1.txtfile2.txtnafonte;issopodeabriraportaparaaextravagânciadatubulação,afimdenãoprecisardearquivosparaduasentradasseparadas,usandodemoeváriosdescritoresdearquivo.

Nenhumdestaquesignificaqueopersonagemestavaemambasaslinhas,destaquesignificaqueestavanoprimeiroevermelhosignificaqueestavanosegundo.

Ascoressãoalteráveisatravésdevariáveisnotopodoscriptevocêpodeatémesmorenunciaràscoresinteiramenteusandocaracteresnormaisparaexpressardiferenças.

#!/bin/bash same='-' #unchanged up='△' #exists in first line, but not in second down='▽' #exists in second line, but not in first reset='' reset=$'\e[0m' same=$reset up=$reset$'\e[1m\e[7m' down=$reset$'\e[1m\e[7m\e[31m' timeout=1 if [[ "$1" != '' ]] then paste -d'\n' "$1" "$2" | "$0" exit fi function demo { "$0" <<EOF Paris in the spring Paris in the the spring A cat on a hot tin roof. a cant on a hot in roof the quikc brown box jupps ober the laze dogs The quickbrown fox jumps over the lazy dogs EOF } # Change \x20 to \x02 to simplify parsing diff's output, #+ then change \x02 back to \x20 for the final output. # Change \x09 to \x01 to simplify parsing diff's output, #+ then change \x01 into → U+1F143 (Squared Latin Capital Letter T) function input { sed \ -e "s/\x09/\x01/g" \ -e "s/\x20/\x02/g" \ -e "s/\(.\)/\n/g" } function output { sed -n \ -e "s/\x01/→/g" \ -e "s/\x02/ /g" \ -e "s/^\(.\) *\x3C$/ \x3C /g" \ -e "s/\(.\) *\(.\) \(.\)$//p" } ifs="$IFS" IFS=$'\n' demo=true while IFS= read -t "$timeout" -r a do demo=false IFS= read -t "$timeout" -r b if [[ $? -ne 0 ]] then echo 'No corresponding line to compare with' > /dev/stderr exit 1 fi diff --text -yt -W 19 \ <(echo "$a" | input) \ <(echo "$b" | input) \ | \ output | \ { type='' buf='' while read -r line do if [[ "${line:1:1}" != "$type" ]] then if [[ "$type" = '|' ]] then type='>' echo -n "$down$buf" buf='' fi if [[ "${line:1:1}" != "$type" ]] then type="${line:1:1}" echo -n "$type" \ | sed \ -e "s/[<|]/$up/" \ -e "s/>/$down/" \ -e "s/ /$same/" fi fi case "$type" in '|') buf="$buf${line:2:1}" echo -n "${line:0:1}" ;; '>') echo -n "${line:2:1}" ;; *) echo -n "${line:0:1}" ;; esac done if [[ "$type" = '|' ]] then echo -n "$down$buf" fi } echo -e "$reset" done IFS="$ifs" if $demo then demo fi     
por 30.10.2017 / 05:02
2

Se eu estou lendo sua pergunta corretamente, eu uso diff -y para esse tipo de coisa.

Torna a comparação de uma comparação lado a lado muito mais simples para descobrir quais linhas estão jogando as diferenças.

    
por 12.04.2011 / 04:29
2
  • xxdiff: Outra ferramenta é o xxdiff (GUI), que deve ser instalado primeiro.
  • planilha: para dados do banco de dados, uma planilha de .csv é facilmente criada e uma fórmula (A7==K7) ? "" : "diff" ou semelhante é inserida e copiada e colada.
por 12.04.2011 / 16:01
2

Aqui está uma simples anotação:

diff -y <(cat a.txt | sed -e 's/,/\n/g') <(cat b.txt | sed -e 's/,/\n/g')

A idéia é substituir vírgulas (ou qualquer delimitador que você queira usar) por novas linhas usando sed . diff cuida do resto.

    
por 02.02.2018 / 17:14
1

Na linha de comando, eu me certificaria de adicionar novas linhas judiciosas antes de comparar os arquivos. Você pode usar sed, awk, perl ou qualquer coisa realmente para adicionar quebras de linha de alguma forma sistemática - certifique-se de não adicionar muitos.

Mas acho que o melhor é usar o vim para destacar as diferenças de palavras. O vim é bom se não houver muitas diferenças e as diferenças forem simples.

    
por 12.04.2011 / 05:02
1
O

kdiff3 está se tornando o visualizador padrão da interface gráfica do usuário no Linux. É semelhante ao xxdiff , mas acho que o kdiff3 é melhor. Ele faz muitas coisas bem, incluindo sua solicitação para mostrar "diferenças de caracteres exatas entre duas linhas em certos arquivos".

    
por 12.04.2011 / 22:42
1

Eu tive o mesmo problema e resolvi com PHP Fine Diff , uma ferramenta on-line que permite para especificar a granularidade. Eu sei que não é tecnicamente uma ferramenta * nix, mas eu realmente não queria baixar um programa apenas para fazer um único diff de nível de caractere.

    
por 23.03.2016 / 22:11