एक पंक्ति के भीतर अंतर करें


113

मेरे पास कुछ एसक्यूएल डंप हैं जो मैं बीच के अंतर को देख रहा हूं। diffस्पष्ट रूप से मुझे दो पंक्तियों के बीच का अंतर दिखा सकता है, लेकिन मैं खुद को पागल कर रहा हूं कि अल्पविराम से अलग किए गए मूल्यों की लंबी सूची में कौन से मूल्यों को खोजने की कोशिश कर रहे हैं, जिससे वास्तव में रेखाएं भिन्न हो सकती हैं।

कुछ फ़ाइलों में दो लाइनों के बीच सटीक वर्ण अंतर को इंगित करने के लिए मैं किस टूल का उपयोग कर सकता हूं?


जवाबों:


93

वहाँ wdiff , उस के लिए शब्द-अलग है।

डेस्कटॉप पर, मिलकर एक हो जाना आप के लिए एक लाइन के भीतर मतभेद उजागर कर सकते हैं।


8
रंगीन wdiff:wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" file1 file2
l0b0

47
रंग के लिए, स्थापित colordiff , तो कार्य करें:wdiff a b | colordiff
philfreo

मेल्ड वास्तव में लाइन-आधारित फ़ाइलों के बीच अंतर-रेखा अंतर दिखाने में बेहद धीमी (मिनट) है
डेन डैस्कलेस्कु

एक dwdiffउपकरण भी है जो अधिकतर संगत है wdiffलेकिन रंगीन आउटपुट और शायद कुछ अन्य विशेषताओं का भी समर्थन करता है। और यह आर्क जैसे कुछ लिनक्स वितरण में अधिक उपलब्ध है।
मार्सॉफ्ट

4
wdiff -n a b | colordiff, सलाह देता है man colordiff
केमिली गौडेय्यून

25

Git-diff का उपयोग करते हुए बस एक अन्य विधि:

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

grep -v यदि अंतर के पदों में रुचि नहीं है।


2
यह ठीक वैसा ही व्यवहार है जिसकी मैं नकल करने की कोशिश कर रहा था - मुझे महसूस नहीं हुआ कि मैं बिना किसी फाइल को अनुक्रमित किए बिना git-diff का उपयोग कर सकता हूं।
पालक

1
--word-diff यहां प्रमुख विकल्प है। धन्यवाद!
user2707671

1
- यदि आप एक गिट वर्किंग डायरेक्टरी में हैं, तो केवल इंडेक्स की आवश्यकता होती है और फू और बार दोनों समान हैं।
xn।

22

मैंने इसके लिए उपयोग किया vimdiffहै।

यहाँ एक स्क्रीनशॉट है (मेरा नहीं) मामूली एक या दो चरित्र अंतर दिखाते हैं जो बहुत अच्छी तरह से बाहर खड़ा है। एक त्वरित ट्यूटोरियल भी


मेरे मामले में अंतर नहीं देखा जा सकता है इसलिए gvim -d f1 f2 में फाइलें खोली गईं, विशेष रूप से लंबी लाइनों को दोनों को अलग-अलग बताया गया, हालांकि वास्तविक अंतर लाल रंग में उजागर किया गया था
zzapper

मैं हमेशा के लिए vim का उपयोग कर रहा हूं, लेकिन vimdiff के बारे में कोई विचार नहीं था!
मिचस

और वर्ण-स्तर के अंतर के लिए diffchar.vim है

2
जितना मुझे vim और vimdiff से प्यार है, एक लाइन में अंतर को उजागर करने के लिए vimdiff का एल्गोरिथ्म बहुत बुनियादी है। यह सामान्य उपसर्ग और प्रत्यय को अलग करने के लिए लगता है, और हर चीज को अलग-अलग रूप में उजागर करता है। यह काम करता है अगर सभी वर्ण जो बदल गए हैं उन्हें एक साथ समूहीकृत किया जाता है, लेकिन अगर वे फैल गए हैं तो यह अच्छी तरह से काम नहीं करता है। यह शब्द-लपेट पाठ के लिए भी भयानक है।
लॉरेंस गोंसाल्वेस

ओपी में लंबी लाइनों के लिए vimdiff -c 'set wrap' -c 'wincmd w' -c 'set wrap' a b, stackoverflow.com/a/45333535/2097284 का सुझाव देता है ।
केमिली गौडेय्यून

6

यहाँ एक "कुत्ते का कुत्ता है कि आप बिट" विधि ...
diffइस बिंदु पर आप मिल गया; आप आगे ले जाने के लिए इसका उपयोग करें ...

यहाँ नमूना लाइन जोड़े का उपयोग करने से आउटपुट है ... एक टैब इंगित करता है

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

यहाँ स्क्रिप्ट है .. आपको बस किसी भी तरह से लाइन जोड़े को बाहर निकालने की ज़रूरत है .. (मैंने आज से पहले केवल एक बार (दो बार?) का उपयोग किया है, इसलिए मुझे इसके कई विकल्प नहीं पता हैं, और इसके लिए विकल्पों को छांटना है। स्क्रिप्ट मेरे लिए, एक दिन के लिए पर्याप्त थी :) .. मुझे लगता है कि यह काफी सरल होना चाहिए, लेकिन मैं कॉफी ब्रेक के कारण हूं ...।

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

wdiffवास्तव में शब्द-दर-शब्द फाइलों की तुलना करने की एक बहुत पुरानी विधि है। यह फ़ाइलों में सुधार करके, फिर diffमतभेद खोजने और इसे फिर से वापस पारित करने के लिए उपयोग करके काम करता है । मैंने खुद संदर्भ जोड़ने का सुझाव दिया, ताकि शब्द-दर-शब्द तुलना के बजाय, यह प्रत्येक शब्द को अन्य 'संदर्भ' शब्दों से घिरा हुआ करता है। यह अनुमति देता है कि फ़ाइलों को सामान्य मार्ग पर फ़ाइलों में खुद को सिंक्रनाइज़ करने के लिए बेहतर है, खासकर जब फाइलें आम शब्दों के केवल कुछ ब्लॉकों के साथ भिन्न होती हैं। उदाहरण के लिए जब साहित्यिक चोरी के लिए पाठ की तुलना, या फिर से उपयोग।

dwdiffबाद में से बनाया गया था wdiffलेकिन dwdiff उस पाठ सुधार कार्य को अच्छे प्रभाव में उपयोग करता है dwfilter। यह एक महान विकास है - इसका मतलब है कि आप एक पाठ को दूसरे से मिलान करने के लिए पुन: स्वरूपित कर सकते हैं, और फिर किसी भी लाइन-बाय-लाइन आलेखीय भिन्न प्रदर्शक का उपयोग करके उनकी तुलना कर सकते हैं। उदाहरण के लिए, इसे "विसरित" ग्राफिकल भिन्न के साथ उपयोग करना ...।

dwfilter file1 file2 diffuse -w

यह file1प्रारूप को सुधारता है file2और diffuseदृश्य तुलना के लिए देता है । file2अनमॉडिफाइड है, इसलिए आप सीधे शब्दों में अंतर को संपादित और मर्ज कर सकते हैं diffuse। यदि आप संपादित करना चाहते हैं file1, तो आप -rरिवर्स में जोड़ सकते हैं कि कौन सी फ़ाइल का सुधार हुआ है। यह कोशिश करो और आप पाएंगे यह बहुत शक्तिशाली है!

ग्राफिकल फ़र्क (ऊपर दिखाया गया है) के लिए मेरी प्राथमिकता वैसी ही है diffuseजैसा कि यह दूर तक साफ करने वाला और अधिक उपयोगी लगता है। इसके अलावा यह एक स्टैंडअलोन पायथन प्रोग्राम है, जिसका अर्थ है कि अन्य UNIX सिस्टम को स्थापित करना और वितरित करना आसान है।

अन्य चित्रमय भिन्नताओं पर बहुत अधिक निर्भरताएं हैं, लेकिन उनका उपयोग भी किया जा सकता है (आप पसंद करते हैं)। इनमें शामिल हैं kdiff3या xxdiff


4

एक आधार के रूप में @ पीटर के समाधान का उपयोग करके मैंने इसमें कई बदलाव किए।

यहाँ छवि विवरण दर्ज करें

  • यह केवल प्रत्येक पंक्ति को एक बार प्रिंट करता है, आपको अंतर दिखाने के लिए रंग का उपयोग करता है।
  • यह किसी भी अस्थायी फ़ाइलों को नहीं लिखता है, इसके बजाय सब कुछ पाइपिंग करता है।
  • आप दो फ़ाइल नाम प्रदान कर सकते हैं और यह प्रत्येक फ़ाइल में संबंधित लाइनों की तुलना करेगा। ./hairOfTheDiff.sh file1.txt file2.txt
  • अन्यथा, यदि आप मूल प्रारूप का उपयोग करते हैं (पहले की तुलना में हर दूसरी पंक्ति के साथ एक एकल फ़ाइल की आवश्यकता होती है) तो अब आप इसे बस पाइप कर सकते हैं, किसी फ़ाइल को पढ़ने के लिए मौजूद होने की आवश्यकता नहीं है। demoस्रोत में एक नज़र रखना ; यह दो अलग-अलग इनपुटों के लिए फाइलों का उपयोग न करने के लिए pasteऔर कई फाइल-डिस्क्रिप्टर के लिए भी फैंसी पाइपिंग का दरवाजा खोल सकता है ।

कोई हाइलाइट का मतलब चरित्र दोनों लाइनों में था, हाइलाइट का मतलब यह पहले में था, और लाल का मतलब यह दूसरे में था।

रंग स्क्रिप्ट के शीर्ष पर चर के माध्यम से परिवर्तनशील होते हैं और आप मतभेदों को व्यक्त करने के लिए सामान्य वर्णों का उपयोग करके पूरी तरह से रंगों को भी बदल सकते हैं।

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

यहाँ एक साधारण लाइनर है:

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

विचार का उपयोग अल्पविराम (या जो भी आप उपयोग करना चाहते हैं परिसीमा को बदलने के लिए है) को न्यूलाइन्स का उपयोग करके करना है seddiffफिर बाकी का ख्याल रखता है।


2
  • xxdiff: एक अन्य उपकरण xxdiff (GUI) है, जिसे पहले स्थापित किया जाना है।
  • स्प्रेडशीट: डेटाबेस डेटा के लिए, एक स्प्रेडशीट .csvआसानी से बनाई जाती है, और एक सूत्र (A7==K7) ? "" : "diff"या समान डाला जाता है, और कॉपी-पेस्ट किया जाता है।

1
xxdiff 80 के दशक जैसा दिखता है। मेल्ड ज्यादा बेहतर दिखता है लेकिन यह CSV जैसी फाइलों के लिए बेहद धीमा है। मैंने पाया है कि डिफ्यूज़ सबसे तेज़ लिनक्स डिफ टूल है।
डैन डस्केल्सस्कु

@DanDascalescu: एक उपकरण जो काम करवाता है वह हमेशा ठीक दिखता है, चाहे वह कितना भी पुराना क्यों न लग रहा हो। एक और, मैंने कभी-कभी उपयोग किया, लेकिन इसे लंबे, स्तंभ डेटा के साथ परीक्षण करने के लिए स्थापित नहीं किया गया है, यह tkdiff है
उपयोगकर्ता अज्ञात

क्या xxdiff प्रदर्शित लाइनों को स्थानांतरित करता है ? या यह सिर्फ एक फ़ाइल में एक लापता लाइन और दूसरे में एक जोड़ा जाता है? (मैंने xxdiff बनाने की कोशिश की, लेकिन qmake विफल रहा और मुझे लगता है कि वे डेबियन पैकेज प्रकाशित करने के लिए परेशान नहीं हैं)।
डेन डैस्कलेस्कु

@DanDascalescu: आज, मेरे पास केवल tkdiff स्थापित है।
उपयोगकर्ता अज्ञात

1

कमांड लाइन पर, मैं यह सुनिश्चित करूँगा कि मैं फाइलों की तुलना करने से पहले विवेकपूर्ण नई लाइनें जोड़ूँ। आप किसी प्रकार के व्यवस्थित तरीके से लाइन ब्रेक जोड़ने के लिए वास्तव में sed, awk, perl या किसी भी चीज़ का उपयोग कर सकते हैं - यह सुनिश्चित करें कि आप इसे बहुत अधिक न जोड़ें।

लेकिन मुझे सबसे अच्छा लगता है विम का उपयोग करना क्योंकि यह शब्द के अंतर को उजागर करता है। vim अच्छा है यदि बहुत अधिक अंतर नहीं हैं और अंतर सरल हैं।


हालांकि वास्तव में इस सवाल का जवाब नहीं है कि यह तकनीक लंबी लाइनों में छोटे अंतर के बारे में जानने के लिए कुशल है।
jknappen

1

kdiff3 Linux पर मानक GUI भिन्न दर्शक बन रहा है। यह xxdiff के समान है , लेकिन मुझे लगता है कि kdiff3 बेहतर है। यह कई चीजों को अच्छी तरह से करता है, जिसमें "कुछ फ़ाइलों में दो लाइनों के बीच सटीक चरित्र अंतर" दिखाने का आपका अनुरोध भी शामिल है।


KDV3 CSV फ़ाइलों में इनलाइन अंतरों को उजागर करने के लिए बेहद धीमा है। मैं इसकी सिफारिश नहीं करूंगा।
डेन डैस्कलेस्कु

1

अगर मैं आपके प्रश्न को सही ढंग से पढ़ रहा हूं, तो मैं diff -yइस तरह का उपयोग करता हूं ।

यह एक पक्ष की तुलना को बहुत सरल तुलना करके यह पता लगाने के लिए करता है कि कौन सी रेखाएं मतभेदों को फेंक रही हैं।


1
यह रेखा के भीतर के अंतर को उजागर नहीं करता है। यदि आपके पास एक लंबी लाइन है, तो अंतर देखने के लिए यह दर्दनाक है। wdiff, git diff --word-diff, vimgit, meld, kbdiff3, tkdiff यह सब करते हैं।
user2707671

1

मेरे पास एक ही समस्या थी और इसे PHP फाइन डिफ के साथ हल किया , एक ऑनलाइन टूल जो आपको ग्रैन्युलैरिटी को निर्दिष्ट करने की अनुमति देता है। मुझे पता है कि यह तकनीकी रूप से एक * निक्स उपकरण नहीं है, लेकिन मैं वास्तव में केवल एक बार करने के लिए एक कार्यक्रम डाउनलोड नहीं करना चाहता था, चरित्र का स्तर अलग है।


कुछ उपयोगकर्ता संवेदनशील या बड़ी फ़ाइलों को यादृच्छिक ऑनलाइन टूल पर अपलोड नहीं कर सकते हैं। कर रहे हैं उपकरण है कि लाइन-लेवल अंतर दिखाने के बहुत सारे आपकी गोपनीयता से समझौता किए बिना।
डैन डस्केल्सस्कु

हां, वहां हैं। लेकिन ऐसे अंतरों के लिए जिनमें संवेदनशील जानकारी नहीं होती है, ऑनलाइन टूल एक अच्छा समाधान हो सकता है।
पिल्लवी

ऑनलाइन भिन्न उपकरण भी कमांड लाइन एकीकरण का समर्थन नहीं करते हैं। आप उन्हें अपने संस्करण नियंत्रण प्रवाह से उपयोग नहीं कर सकते। वे उपयोग करने के लिए बहुत अधिक बोझिल हैं (फ़ाइल 1 का चयन करें, फ़ाइल 2 का चयन करें, अपलोड करें) और विलय नहीं कर सकते।
दान डैस्कलेस्क्यू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.