我有一些 sql 转储,我正在查看它们之间的差异。diff
可以明显地向我展示两条线之间的差异,但我试图找出一长串逗号分隔值中的哪些值实际上是导致线不同的值,这让我自己发疯。
我可以使用什么工具来指出某些文件中两行之间的确切字符差异?
答案1
答案2
另一种使用 git-diff 的方法:
git diff -U0 --word-diff --no-index -- foo bar | grep -v ^@@
grep -v 如果对差异的位置不感兴趣。
答案3
答案4
使用@Peter.O的解决方案作为基础,我重写了它并进行了一些更改。
- 它只打印每行一次,并使用颜色来显示差异。
- 它不写入任何临时文件,而是通过管道传输所有内容。
- 您可以提供两个文件名,它会比较每个文件中的相应行。
./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