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?
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ů.
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 .
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
#
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
.
Jako základ řešení @ Peter.O jsem jej přepsal, abych provedl řadu změn.
./hairOfTheDiff.sh file1.txt file2.txt
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
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.
.csv
je snadno vyrobitelný a vzorec (A7==K7) ? "" : "diff"
nebo podobné vloženo a kopírováno.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.
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é.
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.