bir çizgi içinde fark


113

Aradaki farklara bakıyorum bazı sql dökümü var. diffAçıkçası bana iki satır arasındaki farkı gösterebilirim, ancak uzun virgülle ayrılmış değerler listesindeki hangi değerlerin aslında satırların farklı olmasına neden olduğunu bulmaya çalışırken kendimi delirtiyorum.

Belirli dosyalarda iki satır arasındaki karakter farklarını belirtmek için hangi aracı kullanabilirim?


Yanıtlar:


93

Orada wdiff , bunun için kelime-diff.

Masaüstünde meld , sizin için bir çizgideki farklılıkları vurgulayabilir.


8
Renkli hırka:wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" file1 file2
l0b0

47
Renk için colordiff'i kurun , sonra şunu yapın:wdiff a b | colordiff
philfreo 28:13

Meld aslında satır tabanlı dosyalar arasındaki satır içi farkları gösterme konusunda son derece yavaştır (dakika) .
Dan Dascalescu

Orada da dwdiffçoğunlukla uyumlu aracı wdiffdeğil, aynı zamanda renkli çıktı ve muhtemelen diğer bazı özellikleri destekler. Ve Arch gibi bazı Linux dağıtımlarında daha kullanılabilir.
MarSoft

4
wdiff -n a b | colordiff, tavsiye eder man colordiff.
Camille Goudeseune

25

Git-diff kullanarak başka bir yöntem:

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

grep -v, diff'in pozisyonlarıyla ilgilenmiyorsa.


2
Bu tam olarak taklit etmeye çalıştığım davranış - bu, indekslenen dosyalardan biri olmadan git-diff kullanabileceğimin farkında değildi.
spinup

1
--word-diff buradaki anahtar seçenektir. Teşekkürler!
user2707671

1
--no-index sadece bir git çalışma dizinindeyseniz ve hem foo hem de bar çalışıyorsa gereklidir.
xn.

22

Bunun vimdiffiçin kullandım .

İşte oldukça iyi göze çarpan küçük bir veya iki karakter farklılığını gösteren bir ekran görüntüsü (benim değil). Çok hızlı bir öğretici .


Benim durumumda, farkı göremediğim için dosyaları gvim -d f1
f2'de açtım

Sonsuza kadar vim kullanıyorum ama vimdiff hakkında hiçbir fikrim yoktu!
mitchus

Ve karakter seviyesi farkları için diffchar.vim var .

2
Vim ve vimdiff'u sevdiğim kadar, vimdiff'un bir çizgideki farklılıkları vurgulamak için kullandığı algoritma oldukça basit. Sadece ortak ön eki ve soneki çıkarır ve aralarındaki her şeyi farklı olarak gösterir. Bu, değiştirilen tüm karakterler bir arada gruplanırsa çalışır, ancak yayılırsa iyi çalışmaz. Ayrıca sözcükle sarılmış metinler için de korkunç.
Laurence Gonsalves

OP uzun hatları için, vimdiff -c 'set wrap' -c 'wincmd w' -c 'set wrap' a banlaşılacağı stackoverflow.com/a/45333535/2097284 .
Camille Goudeseune

6

İşte ".. seni ısırtan köpeğin saçması" yöntemi ...
diffbu noktaya geldin; seni daha ileri götürmek için kullan ...

İşte örnek çizgi çiftlerini kullanmaktan çıkan çıktı ... bir TAB gösterir

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 
║  ║   ^ ║      ║     ║    ║          ║     ^

İşte senaryo .. Sadece satır çiftlerini bir şekilde yükseltmek gerekiyor .. (şimdiden önce sadece bir kez (iki kez? senaryo benim için yeterliydi, bir günlüğüne :) .. Sanırım yeterince basit olmalı, ama bir kahve molası için ....

#
# 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
#

4

wdiffAslında, dosyaları kelimelere göre karşılaştırmanın çok eski bir metodu. Dosyaları yeniden biçimlendirerek çalıştı, sonra difffarklılıkları bulmak için kullandı ve tekrar geri verdi. Ben kendime bağlam eklemeyi önerdim, böylece kelime kelimesi yerine karşılaştırmak yerine, her kelimeyi başka 'bağlam' kelimelerinin çevrelediği şekilde yapıyor. Bu, özellikle dosyaların çoğunlukla birkaç ortak kelime bloğuyla farklı olduğu durumlarda, farkın dosyalardaki ortak geçitlerde kendisini daha iyi eşitlemesini sağlar. Örneğin, intihal için metin karşılaştırırken veya yeniden kullandığınızda.

dwdiffdaha sonra oluşturuldu wdiff. Ancak dwdiff bu metni yeniden biçimlendirme işlevini, iyi etki için kullanır dwfilter. Bu harika bir gelişme - bir metni diğerine eşleştirmek için yeniden biçimlendirebilir ve sonra bunları satır satır grafik fark görüntüleyicisi kullanarak karşılaştırabilirsiniz. Örneğin, "diffuse" grafiksel diff ile kullanma ....

dwfilter file1 file2 diffuse -w

Bu yeniden biçimlendirir file1biçimine file2ve o verdiği diffusegörsel bir karşılaştırma için. file2değiştirilmemiş olduğundan, sözcük farklılıklarını doğrudan içinde düzenleyebilir ve birleştirebilirsiniz diffuse. Düzenlemek file1istiyorsanız, -rhangi dosyanın yeniden biçimlendirildiğini tersine ekleyebilirsiniz . Deneyin ve son derece güçlü olduğunu göreceksiniz!

Grafiksel fark tercihim (yukarıda gösterilmiştir), diffusedaha temiz ve daha faydalı hissettirdiği gibidir . Ayrıca, bağımsız bir python programıdır, diğer UNIX sistemlerine kurulumu ve dağıtımı kolaydır.

Diğer grafiksel farklılıkların çok fazla bağımlılığı var gibi gözüküyor, fakat kullanılabiliyor da (seçiminiz). Bunlar kdiff3veya xxdiff.


4

@ Peter.O'nun çözümünü temel alarak bir dizi değişiklik yapmak için yeniden yazdım.

görüntü tanımını buraya girin

  • Size, farklılıkları göstermek için renk kullanarak her satırı yalnızca bir kez yazdırır.
  • Herhangi bir geçici dosya yazmaz, bunun yerine her şeyi kullanır.
  • İki dosya adı verebilirsiniz ve her dosyadaki karşılık gelen satırları karşılaştıracaktır. ./hairOfTheDiff.sh file1.txt file2.txt
  • Aksi takdirde, orijinal formatı kullanırsanız (her saniye satırının daha öncekiyle karşılaştırılması gereken tek bir dosya), şimdi basitçe içine aktarabilirsiniz, okunacak dosya bulunmasına gerek yoktur. demoKaynağa bir göz atın ; bu, iki ayrı giriş için dosyalara ihtiyaç duymamak için, pasteve birden fazla dosya tanıtıcısını kullanmak için fantezi boruya kapıyı açabilir .

Vurgulama yok, karakterin her iki satırda olduğu anlamına gelir, vurgulama, ilk sırada olduğu anlamına gelir ve kırmızı, ikinci sırada olduğu anlamına gelir.

Renkler betiğin üstündeki değişkenler arasında değiştirilebilir ve farklılıkları ifade etmek için normal karakterleri kullanarak renkleri tamamen bırakabilirsiniz.

#!/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

3

İşte basit bir astar:

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

Fikir, kullanmak istediğiniz yeni satırlarla virgüllerin (veya kullanmak istediğiniz sınırlayıcıların) değiştirilmesidir sed. diffsonra gerisini halleder.


2
  • xxdiff: Başka bir araç, ilk önce kurulması gereken xxdiff (GUI).
  • e-tablo: Veritabanı verileri için, bir e-tablo .csvkolayca yapılır ve bir formül (A7==K7) ? "" : "diff"veya benzeri eklenir ve kopyalanır.

1
xxdiff 80'lere benziyor. Meld çok daha iyi görünüyor ancak CSV benzeri dosyalar için oldukça yavaş. buldum Diffuse en hızlı Linux fark aracı olmak.
Dan Dascalescu

@DanDascalescu: İşi yapan bir araç, kaç yaşında görünüyorsa kalsın her zaman iyi görünüyor. Bir diğeri, arada sırada kullandım, ancak uzun, sütun verileriyle test etmek için kurulmadı tkdiff .
kullanıcı bilinmeyen

Xxdiff taşınan çizgileri gösterir mi mi? Yoksa sadece bir dosyada eksik bir satırı ve diğerinde eklenmiş bir satırı mı gösteriyor? (Xxdiff'i inşa etmeyi denedim ama qmake başarısız oldu ve bir Debian paketi yayınlamak için uğraşmadıklarını görüyorum).
Dan Dascalescu

@DanDascalescu: Bugün sadece tkdiff kurulu.
kullanıcı bilinmeyen

1

Komut satırında, dosyaları karşılaştırmadan önce akıllıca yeni satırlar eklediğimden emin olurdum. Satır sonlarını bir tür sistematik şekilde eklemek için sed, awk, perl veya başka bir şey kullanabilirsiniz - çok fazla eklemediğinizden emin olun.

Ama kelime farklılıklarını vurguladığı için vim kullanmak en iyisidir. Çok fazla fark yoksa ve farklar basitse vim iyidir.


Soruya bir cevap olmasa da, bu teknik uzun çizgilerdeki küçük farklılıkları öğrenmek için oldukça verimlidir.
jknappen

1

kdiff3 , Linux'ta standart GUI diff görüntüleyicisi haline geliyor. Bu benzer xxdiff ama KDiff3 daha iyi olduğunu düşünüyorum. "Belirli dosyalarda iki satır arasındaki karakter karakterlerinin tam karakter farklılıklarını gösterme" isteğinizi de içeren çok şey var.


KDiff3, CSV dosyalarındaki satır içi farkları vurgulamak için son derece yavaştır . Bunu tavsiye etmem.
Dan Dascalescu

1

Sorunuzu doğru okuyorsam, diff -ybu tür şeyler için kullanırım .

Hangi çizgilerin farklılıkları attığını bulmak için yan yana karşılaştırmayı çok daha basit hale getirir.


1
Bu, satır içindeki farkı vurgulamaz. Uzun bir çizginiz varsa, farkı görmek acı vericidir. wdiff, git diff - word-diff, vimgit, meld, kbdiff3, tkdiff hepsini yapar.
user2707671,

1

Aynı sorunu yaşadım ve ayrıntı derecesini belirlemenizi sağlayan çevrimiçi bir araç olan PHP Fine Diff ile çözdüm. Teknik olarak bir * nix aracı olmadığını biliyorum, ancak yalnızca bir kerelik, karakter düzeyinde bir fark yapmak için bir program indirmek istemedim.


Bazı kullanıcılar hassas veya büyük dosyaları rastgele çevrimiçi bir araca yükleyemez. Orada çizgi düzey farklılıkları göstermek araçları bol gizlilik ödün vermeden.
Dan Dascalescu

Evet var. Ancak hassas bilgi içermeyen farklar için, çevrimiçi araçlar iyi bir çözüm olabilir.
pillravi

Çevrimiçi fark araçları ayrıca komut satırı entegrasyonunu desteklemez. Bunları sürüm kontrol akışınızdan kullanamazsınız. Ayrıca kullanmaları çok daha zordur (1. dosyayı seçin, 2. dosyayı seçin, yükleyin) ve birleştirme yapamazlar.
Dan Dascalescu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.