it-swarm-ru.tech

различие в линии

У меня есть несколько дампов SQL, которые я смотрю на различия между. diff, очевидно, может показать мне разницу между двумя строками, но я схожу с ума, пытаясь найти, какие значения в длинном списке значений, разделенных запятыми, на самом деле являются теми, которые вызывают различия строк.

Какой инструмент я могу использовать, чтобы указать точные символьные различия между двумя строками в определенных файлах?

120
user394

Для этого есть wdiff , Word-diff.

На рабочем столе meld может выделить различия в строке для вас.

96
alex

Еще один метод, использующий git-diff:

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

grep -v, если не интересует положение различий.

31
Deepak

Я использовал vimdiff для этого.

Вот скриншот (не мое), показывающее незначительные различия в одном или двух символах, которые очень хорошо выделяются. A быстрое руководство тоже .

24
Mark McKinstry

Вот метод "... волосы собаки, которая укусила тебя" ...
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 
║  ║   ^ ║      ║     ║    ║          ║     ^

Вот сценарий ... Вам просто нужно как-то найти пары линий ... (я использовал diff только один раз (два раза?) До сегодняшнего дня, поэтому я не знаю его много вариантов, и разбираюсь с вариантами для этого сценария мне хватило, на один день :) .. думаю, он должен быть достаточно простым, но я должен на кофе-брейк ....

#
# 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 на самом деле очень старый метод сравнения файлов Word-by-Word. Он работал, переформатируя файлы, затем используя diff, чтобы найти различия и передавая их снова. Я сам предложил добавить контекст, чтобы вместо сравнения по словам он делал это с каждым Словом, окруженным другими словами "контекста". Это позволяет diff лучше синхронизировать себя на общих местах в файлах, особенно когда файлы в основном отличаются только несколькими блоками общих слов. Например, при сравнении текста на предмет плагиата или повторного использования.

dwdiff позже был создан из wdiff. Но dwdiff эффективно использует эту функцию переформатирования текста в dwfilter. Это отличная разработка - это означает, что вы можете переформатировать один текст, чтобы он соответствовал другому, а затем сравнить их с помощью любого построчного графического средства отображения различий. Например, используя его с "диффузным" графическим diff ....

dwfilter file1 file2 diffuse -w

Это переформатирует file1 в формате file2 и ​​передает это diffuse для визуального сравнения. file2 не изменяется, поэтому вы можете редактировать и объединять различия Word в него непосредственно в diffuse. Если вы хотите редактировать file1, можете добавить -r чтобы поменять, какой файл переформатирован. Попробуйте, и вы найдете, что это очень мощный!

Я предпочитаю графический интерфейс diff (показанный выше): diffuse , так как он выглядит намного чище и полезнее. Также это отдельная программа python), что означает, что ее легко установить и распространить на другие системы UNIX.

Другие графические различия, кажется, имеют много зависимостей, но также могут быть использованы (на ваш выбор). К ним относятся kdiff3 или xxdiff .

5
anthony

Используя в качестве основы @ Peter.O's solution , я переписал его, чтобы внести ряд изменений.

enter image description here

  • Он печатает каждую строку только один раз, используя цвет, чтобы показать вам различия.
  • Он не записывает никаких временных файлов, а вместо этого передает все.
  • Вы можете указать два имени файла, и он будет сравнивать соответствующие строки в каждом файле. ./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
4
Hashbrown

Вот простой однострочник:

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

Идея состоит в том, чтобы заменить запятые (или любой разделитель, который вы хотите использовать) на новые строки, используя sed. diff тогда позаботится обо всем остальном.

3
user82160
  • xxdiff: еще один инструмент - xxdiff (GUI), который должен быть установлен в первую очередь.
  • электронная таблица: для данных базы данных - электронная таблица из .csv легко сделать, и формула (A7==K7) ? "" : "diff" или аналогичные вставлены и скопированы.
2
user unknown

Если я правильно читаю ваш вопрос, я использую diff -y для такого рода вещей.

Это делает сравнение параллельным сравнением намного проще, чтобы найти, какие строки выбрасывают различия.

1
rfelsburg

В командной строке я хотел бы убедиться, что я добавил разумные новые строки, прежде чем сравнивать файлы. Вы можете использовать sed, awk, Perl или что-нибудь действительно, чтобы добавлять разрывы строк каким-то систематическим способом - убедитесь, что не добавляете слишком много.

Но я считаю, что лучше всего использовать vim, поскольку он подчеркивает различия в Word. vim хорош, если различий не так много, а различия просты.

1
asoundmove

У меня была такая же проблема, и я решил ее с помощью PHP Fine Diff , онлайн-инструмента, который позволяет вам определять гранулярность. Я знаю, что это технически не инструмент * nix, но я действительно не хотел загружать программу просто для того, чтобы выполнить разовую разность уровней персонажа.

1
pillravi

kdiff становится стандартным средством просмотра различий GUI в Linux. Это похоже на xxdiff , но я думаю, что kdiff3 лучше. Он хорошо справляется со многими задачами, включая ваш запрос показать "точные различия символов между двумя строками в определенных файлах".

1
Faheem Mitha