diff dentro de una línea

Tengo algunos vertederos sql que estoy mirando las diferencias entre. diff puede obviamente mostrarme la diferencia entre dos líneas, pero estoy volviendo loco tratando de encontrar qué valores en la larga list de valores separados por comas son realmente los que hacen que las líneas sean diferentes.

¿Qué herramienta puedo usar para señalar las diferencias de caracteres exactas entre dos líneas en ciertos files?

Hay wdiff , la palabra-diff para eso.

En el escritorio, Meld puede resaltar las diferencias dentro de una línea.

He usado vimdiff para esto.

Aquí hay una captura de pantalla (no la mía) que muestra diferencias menores de uno o dos caracteres que se destacan bastante bien. Un tutorial rápido también .

Aquí hay un método del "pelo del perro que te mordió" …
diff te llevó a este punto; Úselo para llevarlo más lejos …

Aquí está el resultado del uso de los pares de líneas de muestra … indica un 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 ║ ║ ^ ║ ║ ║ ║ ║ ^ 

Aquí está el guión … Solo tienes que descubrir los pares de líneas de alguna manera … (He usado diff solo una vez (¿dos veces?) Antes de hoy, así que no conozco sus muchas opciones, y estoy clasificando las opciones para esto el guión fue suficiente para mí, por un día 🙂 .. Creo que debe ser lo suficientemente simple, pero me espera un descanso para tomar café …

 # # 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/\(.\)/\1\n/g") \ <(echo "${pair[1]}" |sed -e "s/\x09/\x01/g" -e "s/\x20/\x02/g" -e "s/\(.\)/\1\n/g") \ |sed -e "s/\x01/☻/g" -e "s/\x02/ /g" \ |sed -e "s/^\(.\) *\x3C$/\1 \x3C /g" \ |sed -n "s/\(.\) *\(.\) \(.\)$/\1\2\3/p" \ >"$workd/out" # (gedit "$workd/out" &) <"$workd/out" sed -e "s/^\(.\)..$/\1/" |tr -d '\n' ;echo <"$workd/out" sed -e "s/^..\(.\)$/\1/" |tr -d '\n' ;echo <"$workd/out" sed -e "s/^.\(.\).$/\1/" -e "s/|/║/" -e "s/</^/" -e "s/>/v/" |tr -d '\n' ;echo echo ((ix=0)) fi done <"$ifile" IFS="$ifs" ;set +f exit # 

Solo otro método usando git-diff:

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

grep -v si no está interesado en las posiciones de los diffs.

wdiff es en realidad un método muy antiguo para comparar files palabra por palabra. Funcionó formateando files, luego usando diff para encontrar diferencias y volver a pasarlas. Yo mismo sugerí agregar context, de modo que en lugar de comparación palabra por palabra, lo hace con cada palabra rodeada de otras palabras de 'context'. Eso permite que el diff se sincronice mucho mejor en pasajes comunes de los files, especialmente cuando los files son en su mayoría diferentes con solo unos pocos bloques de palabras comunes. Por ejemplo, al comparar text para plagio o reutilización.

dwdiff fue creado más tarde desde wdiff . Pero dwdiff usa esa function de reformateo de text con buen efecto en dwfilter . Este es un gran desarrollo: significa que puede reformatear un text para que coincida con otro, y luego compararlo usando cualquier visualizador de diferencias gráfico línea por línea. Por ejemplo, usándolo con diff gráfico "difuso".

 dwfilter file1 file2 diffuse -w 

Esto reformatea el file1 al formatting del file2 y lo diffuse para una comparación visual. file2 no está modificado, por lo que puede editar y combinar diferencias de palabras directamente en diffuse . Si desea editar el file file1 , puede agregar -r para revertir qué file se reformateará. ¡Pruébalo y encontrarás que es extremadamente poderoso!

Mi preference por la diferencia gráfica (que se muestra arriba) es diffuse ya que se siente mucho más limpia y más útil. También es un progtwig de python independiente, lo que significa que es fácil de instalar y distribuir a otros sistemas UNIX.

Otras diferencias gráficas parecen tener muchas dependencies, pero también se pueden usar (usted elige). Estos incluyen kdiff3 o xxdiff .

Si estoy leyendo tu pregunta correctamente, uso diff -y para este tipo de cosas.

Hace que comparar una comparación lado a lado sea mucho más simple para encontrar qué líneas arrojan las diferencias.

  • xxdiff: Otra herramienta es xxdiff (GUI), que debe instalarse primero.
  • spreadsheet: para los datos de la database, se hace fácilmente una spreadsheet de .csv y una fórmula (A7==K7) ? "" : "diff" (A7==K7) ? "" : "diff" o similar insertado, y copydo y pegado.

En la línea de command, me aseguraría de agregar líneas nuevas juiciosas antes de comparar files. Puedes usar sed, awk, perl o cualquier otra cosa para agregar saltos de línea de alguna manera sistemática; sin embargo, asegúrate de no agregar demasiados saltos de línea.

Pero creo que lo mejor es usar vim ya que resalta las diferencias de palabras. vim es bueno si no hay demasiadas diferencias y las diferencias son simples.

kdiff3 se está convirtiendo en el visualizador de diferencias GUI estándar en Linux. Es similar a xxdiff , pero creo que kdiff3 es mejor. Hace muchas cosas bien, incluida su request para mostrar "diferencias de caracteres exactas entre dos líneas en ciertos files".

Tuve el mismo problema y lo resolví con PHP Fine Diff , una herramienta en línea que le permite especificar la granularidad. Sé que técnicamente no es una herramienta * nix, pero realmente no quería download un progtwig solo para hacer una única diferencia de nivel de personaje.

Usando la solución de @ Peter.O como base, la reescribí para hacer una serie de cambios.

enter image description here

  • Solo imprime cada línea una vez, usando color para mostrarle las diferencias.
  • No escribe ningún file temporal, sino que canaliza todo.
  • Puede proporcionar dos nombres de file y comparará las líneas correspondientes en cada file. ./hairOfTheDiff.sh file1.txt file2.txt
  • De lo contrario, si utiliza el formatting original (un solo file con cada segunda línea debe ser comparado con el anterior), ahora puede simplemente canalizarlo, no es necesario que exista ningún file para leer. Eche un vistazo a la demo en la fuente; esto puede abrir la puerta a tuberías lujosas para no necesitar files para dos inputs separadas, usando paste y múltiples descriptores de files.

Sin resaltar significa que el personaje estaba en ambas líneas, resaltado significa que estaba en la primera, y rojo significa que estaba en la segunda.

Los colors son modificables mediante variables en la parte superior del guion e incluso puede omitir los colors por completo mediante el uso de caracteres normales para express las diferencias.

 #!/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 (Squanetworking Latin Capital Letter T) function input { sed \ -e "s/\x09/\x01/g" \ -e "s/\x20/\x02/g" \ -e "s/\(.\)/\1\n/g" } function output { sed -n \ -e "s/\x01/→/g" \ -e "s/\x02/ /g" \ -e "s/^\(.\) *\x3C$/\1 \x3C /g" \ -e "s/\(.\) *\(.\) \(.\)$/\1\2\3/p" } ifs="$IFS" IFS=$'\n' demo=true while IFS= read -t "$timeout" -ra do demo=false IFS= read -t "$timeout" -rb 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