[英]BASH - Comparing two files and redirecting the output to something readable
我需要在服務器上的兩個文件上進行比較,並讓輸出包含標頭或其他指示,以表明差異在哪里。
該腳本當前運行命令列表,並根據輸出創建文件。 輸出類似於以下內容:
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
每天晚上12點,cron將運行此腳本並使用當前設備及其寄存器設置創建第二個文件,因此我可以比較前幾天的寄存器-當前正在使用:
diff -u file1.txt file2.txt > filediff.txt
如果filediff.txt為空,它將刪除diff,並將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
只是一點點,用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
您可以將-C <n>
傳遞給diff
以獲取更改兩側的n行上下文。 不幸的是,這與統一的diff格式-u
不兼容,因此您必須處理格式不同的diff。
例如,在每次更改上方和下方獲得5條上下文:
diff -C 5 file1.txt file2.txt > filediff.txt
旁注:如果您正在處理c代碼,那么-p
標志非常有用-對於每個diff塊,它為您提供更改所在的c函數的名稱。它不是100%准確的,但是在更改時非常有用快速直觀地掃描差異。 我認為這也適用於c ++ , java和javascript ,盡管我沒有嘗試過。
這是一個非常復雜的解決方案:
$ 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.