BASH - 比较两个文件并将输出重定向到可读的内容

时间:2014-04-04 14:58:53

标签: linux bash diff

我需要对服务器上的两个文件进行比较,并让该输出包含标题或其他指示,以了解差异的位置。

脚本当前运行命令列表并根据输出创建文件。输出类似于:

Device 1
Register A value1
Register B value2
Register C value4
...
Register H value5
Device 2
Register A value1
Register B value2
Register C value4
...
Register H value5

每天午夜,cron将运行此脚本并使用当前设备及其寄存器设置创建第二个文件,因此我可以比较前几天的寄存器 - 当前使用:

diff -u file1.txt file2.txt > filediff.txt

如果filediff.txt为空,则删除差异,并将file1.txt移动到file2.txt并删除file1.txt,所以我只剩下file1.txt。

如果filediff.txt文件非空,我会得到类似于以下内容的输出:

-Register B value2
+Register B value3

问题是:由于diff输出的长度,我丢失了具有差异的设备名称,除非该差异接近设备名称。是否有我可以添加到diff命令的标志,或者检查两个文件之间差异的不同方法,包括更多或全部的寄存器值,以便我可以获取设备名称和寄存器更改(旧所以我可以把它们放到一个文本文件中进行报告:

Device 1
Old Register R value18
New Register R value23

3 个答案:

答案 0 :(得分:1)

只是对它来说,使用awk进行后期处理会是什么样子呢

diff -u file1.txt file2.txt | \
    awk -F ' ' '( DEVICE_VAR ~ "" && $1 == "Device"){print DEVICE_VAR "\nOld " FILE1_VAR "\nNew " FILE2_VAR; FILE1_VAR = ""; FILE2_VAR = ""}
                ( $1 == "Device"){DEVICE_VAR = $0} 
                ( $1 == "-Register"){FILE1_VAR = FILE1_VAR " | " $0 } 
                ( $1 == "+Register"){FILE2_VAR = FILE2_VAR " | " $0 }
                END {print DEVICE_VAR "\nOld " FILE1_VAR "\nNew " FILE2_VAR}'

FILE1.TXT:

Device 1
Register A value1
Register B value2
Register C value4
Device 2
Register A value1
Register B value2
Register C value4

FILE2.TXT:

Device 1
Register A value6
Register B value7
Register C value8
Device 2
Register A value4
Register B value4
Register C value6

输出:

Old 
New 
 Device 1
Old  | -Register A value1 | -Register B value2 | -Register C value4
New  | +Register A value6 | +Register B value7 | +Register C value8
 Device 2
Old  | -Register A value1 | -Register B value2 | -Register C value4
New  | +Register A value4 | +Register B value4 | +Register C value6

答案 1 :(得分:0)

您可以将-C <n>传递给diff,以便在更改的任何一侧获得n行上下文。不幸的是,这与统一的差异格式-u不兼容,所以你必须处理不同格式的差异。

E.g。在每次更改的上方和下方获得5行上下文:

diff -C 5 file1.txt file2.txt > filediff.txt

旁注:如果您正在处理代码,那么-p标志非常有用 - 对于每个差异块,它会为您提供函数的名称改变是在。它不是100%准确,但在快速视觉扫描差异时非常有用。我认为这适用于,但我还没试过。

答案 2 :(得分:0)

这是一个非常复杂的解决方案:

$ cat file1.txt
Device 1
Register A yesterdays_value1
Register B yesterdays_value2
Register C yesterdays_value4
...
Register H yesterdays_value5
Device 2
Register A yesterdays_value1
Register B yesterdays_value2
Register C yesterdays_value4
...
Register H yesterdays_value5

$ cat file2.txt
Device 1
Register A yesterdays_value1
Register B yesterdays_value2
Register C todays_value44
...
Register H yesterdays_value5
Device 2
Register A yesterdays_value1
Register B todays_value22
Register C yesterdays_value4
...
Register H yesterdays_value5

$ comm <(cat -n file1.txt) <(cat -n file2.txt) |  awk '
    function print_clean(prefix) {
        sub(/^[[:space:]]+[0-9]+\t/, prefix) 
        print
    }
    /^\t\t/ {if (/Device/) print_clean(""); next} 
    /^\t/   {print_clean("New "); next} 
            {print_clean("Old ")}
'
Device 1
New Register C todays_value44
Old Register C yesterdays_value4
Device 2
New Register B todays_value22
Old Register B yesterdays_value2

注意:

  • comm要求对其输入文件进行排序。在不重新排列行的情况下对任何文件进行排序的方法是在行前面加上行号。因此cat -n进程替换。
  • comm输出带有2个前导标签的公共线,仅在file2中有1个前导标签的行和仅在file1中没有前导标签的行。因此awk模式。

查看是否存在差异的更好的测试是使用diff -q

if diff -q file1.txt file2.txt; then
    echo no diff
fi