it-swarm-vi.com

khác trong một dòng

Tôi có một số bãi sql mà tôi đang xem xét sự khác biệt giữa. diff rõ ràng có thể cho tôi thấy sự khác biệt giữa hai dòng, nhưng tôi đang tự mình cố gắng tìm các giá trị nào trong danh sách dài các giá trị được phân tách bằng dấu phẩy thực sự là các giá trị làm cho các dòng khác nhau.

Tôi có thể sử dụng công cụ nào để chỉ ra sự khác biệt chính xác giữa hai dòng trong một số tệp nhất định?

120
user394

wdiff , Word-diff cho điều đó.

Trên máy tính để bàn, meld có thể làm nổi bật sự khác biệt trong một dòng cho bạn.

96
alex

Chỉ là một phương pháp khác sử dụng git-diff:

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

grep -v nếu không quan tâm đến vị trí của diffs.

31
Deepak

Tôi đã sử dụng vimdiff cho việc này.

Đây là ảnh chụp màn hình (không phải của tôi) hiển thị một hoặc hai điểm khác biệt nhỏ xuất hiện khá tốt. A hướng dẫn nhanh quá .

24
Mark McKinstry

Đây là một phương pháp "..hair of the dog that bit you" ...
[.__.] diff đưa bạn đến điểm này; sử dụng nó để đưa bạn đi xa hơn ...

Đây là đầu ra từ việc sử dụng các cặp dòng mẫu ... biểu thị 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 
║  ║   ^ ║      ║     ║    ║          ║     ^

Đây là kịch bản .. Bạn chỉ cần tìm ra các cặp dòng bằng cách nào đó .. (Tôi đã sử dụng diff chỉ một lần (hai lần?) Trước ngày hôm nay, vì vậy tôi không biết nhiều tùy chọn của nó và sắp xếp các tùy chọn cho việc này kịch bản là đủ cho tôi, trong một ngày :) .. Tôi nghĩ nó phải đủ đơn giản, nhưng tôi sắp nghỉ cà phê ....

#
# 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 thực sự là một phương pháp rất cũ để so sánh các tệp Word-by-Word. Nó hoạt động bằng cách định dạng lại các tệp, sau đó sử dụng diff để tìm sự khác biệt và gửi lại. Bản thân tôi đã đề xuất thêm ngữ cảnh, để thay vì so sánh từng từ, nó thực hiện với từng từ được bao quanh bởi các từ 'ngữ cảnh' khác. Điều đó cho phép diff tự đồng bộ hóa trên các đoạn phổ biến trong các tệp tốt hơn nhiều, đặc biệt là khi các tệp hầu hết khác nhau chỉ với một vài khối từ phổ biến. Ví dụ: khi so sánh văn bản cho đạo văn, hoặc sử dụng lại.

dwdiff sau đó được tạo từ wdiff. Nhưng dwdiff sử dụng chức năng định dạng lại văn bản đó để có hiệu quả tốt trong dwfilter. Đây là một sự phát triển tuyệt vời - nó có nghĩa là bạn có thể định dạng lại một văn bản để khớp với văn bản khác, và sau đó so sánh chúng bằng bất kỳ trình hiển thị khác biệt đồ họa từng dòng. Ví dụ: sử dụng nó với "diffuse" đồ họa diff ....

dwfilter file1 file2 diffuse -w

Định dạng lại này file1 theo định dạng của file2 và đưa nó cho diffuse để so sánh trực quan. file2 không được sửa đổi, vì vậy bạn có thể chỉnh sửa và hợp nhất các khác biệt của Word vào nó trực tiếp trong diffuse. Nếu bạn muốn chỉnh sửa file1, bạn có thể thêm -r để đảo ngược tập tin nào được định dạng lại. Hãy thử nó và bạn sẽ thấy nó vô cùng mạnh mẽ!

Sở thích của tôi cho khác biệt đồ họa (hiển thị ở trên) là diffuse vì nó cảm thấy sạch sẽ hơn và hữu ích hơn. Ngoài ra, nó là một chương trình độc lập python, có nghĩa là nó dễ dàng cài đặt và phân phối cho các hệ thống UNIX khác.

Khác biệt đồ họa khác dường như có rất nhiều phụ thuộc, nhưng cũng có thể được sử dụng (bạn chọn). Bao gồm các kdiff3 hoặc xxdiff .

5
anthony

Sử dụng @ Peter.O's giải pháp làm cơ sở tôi viết lại nó để thực hiện một số thay đổi.

enter image description here

  • Nó chỉ in mỗi dòng một lần, sử dụng màu sắc để cho bạn thấy sự khác biệt.
  • Nó không viết bất kỳ tập tin tạm thời nào, thay vào đó là mọi thứ.
  • Bạn có thể cung cấp hai tên tệp và nó sẽ so sánh các dòng tương ứng trong mỗi tệp. ./hairOfTheDiff.sh file1.txt file2.txt
  • Mặt khác, nếu bạn sử dụng định dạng ban đầu (một tệp duy nhất với mỗi dòng thứ hai cần được so sánh với tệp trước đó) thì bây giờ bạn có thể chỉ cần đặt nó vào, không cần phải đọc tệp. Hãy xem demo trong nguồn; điều này có thể mở ra cánh cửa cho các đường ống ưa thích để không cần các tệp cho hai đầu vào riêng biệt, sử dụng paste và nhiều mô tả tệp.

Không có điểm nổi bật có nghĩa là nhân vật ở cả hai dòng, nổi bật có nghĩa là ở phần đầu tiên và màu đỏ có nghĩa là ở phần thứ hai.

Màu sắc có thể thay đổi thông qua các biến ở đầu tập lệnh và bạn thậm chí có thể từ bỏ màu hoàn toàn bằng cách sử dụng các ký tự bình thường để thể hiện sự khác biệt.

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

Đây là một lót đơn giản:

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

Ý tưởng là thay thế dấu phẩy (hoặc bất kỳ dấu phân cách nào bạn muốn sử dụng) bằng dòng mới bằng cách sử dụng sed. diff sau đó chăm sóc phần còn lại.

3
user82160
  • xxdiff: Một công cụ khác là xxdiff (GUI), trước tiên phải được cài đặt.
  • bảng tính: Đối với dữ liệu cơ sở dữ liệu, một bảng tính từ .csv dễ dàng thực hiện và một công thức (A7==K7) ? "" : "diff" hoặc tương tự được chèn và dán sao chép.
2
user unknown

Nếu tôi đọc chính xác câu hỏi của bạn, tôi sử dụng diff -y cho loại điều này.

Nó làm cho việc so sánh một so sánh cạnh nhau đơn giản hơn nhiều để tìm ra dòng nào đang tạo ra sự khác biệt.

1
rfelsburg

Trên dòng lệnh, tôi sẽ đảm bảo rằng tôi thêm các dòng mới hợp lý trước khi so sánh các tệp. Bạn có thể sử dụng sed, awk, Perl hoặc bất cứ thứ gì thực sự để thêm ngắt dòng theo một cách nào đó có hệ thống - đảm bảo không thêm quá nhiều mặc dù.

Nhưng tôi thấy tốt nhất là sử dụng vim vì nó làm nổi bật sự khác biệt của Word. vim là tốt nếu không có quá nhiều sự khác biệt và sự khác biệt là đơn giản.

1
asoundmove

Tôi đã có cùng một vấn đề và giải quyết nó với PHP Fine Diff , một công cụ trực tuyến cho phép bạn chỉ định mức độ chi tiết. Tôi biết về mặt kỹ thuật nó không phải là một công cụ * nix, nhưng tôi không thực sự muốn tải xuống một chương trình chỉ để thực hiện một mức độ khác nhau, một lần.

1
pillravi

kdiff đang trở thành trình xem khác biệt GUI tiêu chuẩn trên Linux. Nó tương tự như xxdiff , nhưng tôi nghĩ kdiff3 tốt hơn. Nó thực hiện nhiều điều tốt, bao gồm cả yêu cầu của bạn để hiển thị "sự khác biệt chính xác giữa hai dòng trong một số tệp nhất định".

1
Faheem Mitha