简体   繁体   中英

How to show merged differences between two files?

How can I get only diff letters between two files?

For example,

file1:

 aaa;bbb;ccc 123;456;789 a1a;b1b;c1c 

file2:

 aAa;bbb;ccc 123;406;789 a1a;b1b;c5c 

After diff I should get only this string of difference from the second file: A05

diff -y --suppress-common-lines <(fold -w 1 file1) <(fold -w 1 file2) |
sed 's/.*\(.\)$/\1/' | paste -s -d '' -

This uses process substitution with fold to turn each file into a column of characters that's one character wide and then compares them with diff .

The -y option prints lines next to each other, and --suppress-common-lines skips lines that are the same between both files. Until here, the output looks like this:

$ diff -y --suppress-common-lines <(fold -w 1 file1) <(fold -w 1 file2)
a                                 | A
5                                 | 0
1                                 | 5

We're only interested in the the last character of each line. We use sed to discard the rest:

$ diff -y --suppress-common-lines <(fold -w 1 file1) <(fold -w 1 file2) |
> sed 's/.*\(.\)$/\1/'
A
0
5

To get these into a single line, we pipe to paste with the -s option (serial) and the empty string as the delimiter ( -d '' ). The dash tells paste to read from standard in.

$ diff -y --suppress-common-lines <(fold -w 1 file1) <(fold -w 1 file2) |
> sed 's/.*\(.\)$/\1/' | paste -s -d '' -
A05

An alternative, if you have the GNU diffutils at your disposal, is cmp :

$ cmp -lb file1 file2 | awk '{print $5}' | tr -d '\n'
A05

cmp compares files byte by byte. The -l option ("verbose") makes it print all the differences, not just the first one; the -b options make it add the ASCII interpretation of the differing bytes:

$ cmp -lb file1 file2
 2 141 a    101 A
18  65 5     60 0
34  61 1     65 5

The awk command reduces this output to the fifth column, and tr removes the newlines.

For the example given, you could compare the files character by character and if there is a difference, print the character of the second file. Here's one way to do that:

paste <(fold -w1 file1) <(fold -w1 file2) | \
while read c1 c2; do [[ $c1 = $c2 ]] || printf $c2; done

For the given example, this will print A05 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM