开发者

How can I diff two files and report the section the diff occurs in?

开发者 https://www.devze.com 2022-12-23 14:34 出处:网络
I h开发者_运维技巧ave two text files with several sections in them.Each section has has a header with the section name (grep can extract all the section names without extracting anything else from the

I h开发者_运维技巧ave two text files with several sections in them. Each section has has a header with the section name (grep can extract all the section names without extracting anything else from the file). How can I report the differences between the two files AND report the section that the difference occurs in? I would also need to be able to report added/missing sections. Ideally, identical sections would not be mentioned in the report at all.


Use diff's --show-function-line parameter :

diff -U 0 --show-function-line='^HEAD ' old-file new-file

It won't report the correct section if it apears only in the output file (for example if you added a new section at the end of the file, the added lines will appear as being in the last section of the old file).

The following script might help, though it's far from being a one-liner. It will print :

  • sections from the old file that have deleted lines, prefixed with " -"
  • sections from the new file that have inserted lines, prefixed with " +"
  • deleted lines (including deleted section headers), prefixed with "+"
  • inserted lines (including new section headers), prefixed with "-"

Here is the script :

#!/bin/bash
# Usage : ./script old-file new-file
diff \
    --new-line-format='+%dn'$'\n' \
    --old-line-format='-%dn'$'\n' \
    --unchanged-line-format='' \
    $1 \
    $2 \
    | \
(
    lnumOld=0;
    lnumNew=0;
    header='NO HEADER'
    printheader=1
    while read lprint; do
        if [ "$((lprint))" -gt 0 ]; then
            sep='+'
            while [ $lnumNew -lt $lprint ]; do
                read line <&4
                if [ "${line#HEAD }" != "$line" ]; then
                    header="$sep$line"
                    printheader=1
                fi
                ((lnumNew++));
            done
        else
            sep='-'
            while [ $lnumOld -lt $((-1*$lprint)) ]; do
                read line <&3
                if [ "${line#HEAD }" != "$line" ]; then
                    header="$sep$line"
                    printheader=1
                fi
                ((lnumOld++));
            done
        fi
        if [ $printheader = 1 ]; then
            echo " $header"
            printheader=0
        fi
        echo "$sep$line";
    done) 3<"$1" 4<"$2"


If you introduce an artificial change in the headers, that will force them to show up in the diff. Not exactly what you want, but maybe that will give you an idea.

Assuming your regex for finding headers is ^HEAD:

sed -e 's/^HEAD/>HEAD/' file1.txt | diff -u - file2.txt

Edit: If you want the resulting diff to be a real diff, you can use sed to remove the HEAD difference lines.

sed -e 's/^HEAD/>HEAD/' file1.txt | diff -u - file2.txt | sed -e 's/^->HEAD/ HEAD/; /^+HEAD/D'
0

精彩评论

暂无评论...
验证码 换一张
取 消