it-swarm-eu.dev

rozdíl v řádku

Mám nějaké skládky sql, na které se dívám na rozdíly mezi. diff mi samozřejmě může ukázat rozdíl mezi dvěma řádky, ale snažím se zjistit, které hodnoty v dlouhém seznamu hodnot oddělených čárkami jsou ve skutečnosti ty, které způsobují, že se řádky liší.

Jakým nástrojem mohu poukázat na přesné rozdíly v charakteru mezi dvěma řádky v určitých souborech?

120
user394

Existuje wdiff , Word-diff za to.

Na ploše meld může zvýraznit rozdíly uvnitř řádku pro vás.

96
alex

Jen další metoda používající git-diff:

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

grep -v, pokud nemá zájem o pozice rozdílů.

31
Deepak

K tomu jsem použil vimdiff.

Zde je snímek obrazovky (ne můj) ukazující drobné rozdíly jednoho nebo dvou znaků, které vynikají docela dobře. A také rychlý návod .

24
Mark McKinstry

Tady je metoda "..hair psa, která vás kousla" ...
diff vás dostal k tomuto bodu; použijte ji k dalšímu ...

Zde je výstup z použití párů vzorových čar ... označuje 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 
║  ║   ^ ║      ║     ║    ║          ║     ^

Tady je skript .. Musíte jen fretku z páru řádků nějak nějak ... (Použil jsem diff pouze jednou (dvakrát?) Před dnes, takže nevím, jeho mnoho možností, a třídění možnosti pro toto scénář mi stačil na jeden den :) .. Myslím, že to musí být dost jednoduché, ale já jsem kvůli přestávce na kávu ....

#
# 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
#
6
Peter.O

wdiff je ve skutečnosti velmi stará metoda porovnávání souborů Word-by-Word. Fungovalo to přeformátováním souborů, pomocí diff k nalezení rozdílů a jejich předáním zpět. Sám jsem navrhl přidat kontext, takže spíše než porovnávání Word-by-Word to dělá s každým Slovem obklopeným jinými „kontextovými“ slovy. To umožňuje rozdílu synchronizovat se na běžných pasážích v souborech mnohem lépe, zejména když jsou soubory většinou odlišné pouze s několika bloky běžných slov. Například při porovnávání textu pro plagiátorství nebo opakovaném použití.

dwdiff byl později vytvořen z wdiff. Ale dwdiff používá tuto funkci textového přeformátování v dwfilter. To je skvělý vývoj - to znamená, že můžete přeformátovat jeden text tak, aby odpovídal jinému, a poté je porovnat pomocí libovolného grafického zobrazovače rozdílových řádků. Například jeho použití s ​​"difúzním" grafickým rozdílem ....

dwfilter file1 file2 diffuse -w

Toto přeformátuje file1 do formátu file2 a dává to diffuse pro vizuální srovnání. file2 je nezměněno, takže do něj můžete upravovat a slučovat rozdíly Wordu přímo v diffuse. Pokud chcete upravit file1, můžeš přidat -r pro obrácení, který soubor je přeformátován. Vyzkoušejte to a zjistíte, že je extrémně silný!

Moje preference pro grafický rozdíl (viz výše) je diffuse , protože se cítí mnohem čistší a užitečnější. Je to také samostatný program python), což znamená, že je snadné instalovat a distribuovat do jiných systémů UNIX.

Zdá se, že jiné grafické rozdíly mají spoustu závislostí, ale lze je také použít (podle vašeho výběru). Tyto zahrnují kdiff3 nebo xxdiff .

5
anthony

Jako základ řešení @ Peter.O jsem jej přepsal, abych provedl řadu změn.

enter image description here

  • Vytiskne každý řádek pouze jednou a pomocí barev zobrazí rozdíly.
  • Nezapisuje žádné dočasné soubory, místo toho převádí vše.
  • Můžete zadat dvě jména souborů a porovná odpovídající řádky v každém souboru. ./hairOfTheDiff.sh file1.txt file2.txt
  • V opačném případě, pokud použijete původní formát (jeden soubor s každým druhým řádkem, který je třeba porovnat s předchozím), můžete jej nyní jednoduše zkomprimovat, není nutné číst žádný soubor. Podívejte se na demo ve zdroji; to může otevřít dveře fantazijnímu potrubí, aby se nepotřebovaly soubory také pro dva samostatné vstupy, pomocí paste a více deskriptorů souborů.

Žádné zvýraznění znamená, že znak byl v obou řádcích, zvýraznění znamená, že to bylo v prvním a červené znamená, že to bylo v druhém.

Barvy jsou proměnné v proměnných v horní části skriptu a můžete dokonce vzdát barev zcela pomocí normálních znaků k vyjádření rozdílů.

#!/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/\(.\)/\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" -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
4
Hashbrown

Zde je jednoduchý jednodílný:

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

Záměrem je nahradit čárky (nebo jakýkoli oddělovač, který chcete použít) novými řádky pomocí sed. diff se postará o zbytek.

3
user82160
  • xxdiff: Dalším nástrojem je xxdiff (GUI), který musí být nejprve nainstalován.
  • tabulka: V případě databázových dat tabulka od .csv je snadno vyrobitelný a vzorec (A7==K7) ? "" : "diff" nebo podobné vloženo a kopírováno.
2
user unknown

Pokud čtu vaši otázku správně, používám diff -y za takovou věc.

Díky tomu je porovnání mezi jednotlivými stranami mnohem snazší zjistit, které linie házejí rozdíly.

1
rfelsburg

Na příkazovém řádku bych se před porovnáním souborů ujistil, že přidám rozumné nové řádky. Můžete použít sed, awk, Perl nebo cokoli, co skutečně přidává zalomení řádků nějakým systematickým způsobem - nezapomeňte však přidat příliš mnoho.

Ale zjistil jsem, že nejlepší je použít vim, protože to zdůrazňuje rozdíly ve slovech. vim je dobrý, pokud není příliš mnoho rozdílů a rozdíly jsou jednoduché.

1
asoundmove

Měl jsem stejný problém a vyřešil jsem to pomocí PHP Fine Diff , online nástroje, který vám umožní určit granularitu. Vím, že to není technicky nástroj * nix, ale nechtěl jsem si stáhnout program, jen abych udělal jednorázový, znakový rozdíl.

1
pillravi

kdiff se v Linuxu stává standardním prohlížečem GUI diff. Je to podobné xxdiff , ale myslím, že kdiff3 je lepší. To dělá mnoho věcí dobře, včetně vaší žádosti ukázat "přesné rozdíly v charakteru mezi dvěma řádky v určitých souborech".

1
Faheem Mitha