簡體   English   中英

如何使用 fgrep/comm 比較兩個大文件的唯一字符串?

[英]How to comparing two big files on unique strings using fgrep/comm?

我有兩個文件。 一個文件disk.txt包含57665977行,database.txt包含39035203行;

為了測試我的腳本,我制作了兩個示例文件:

$ cat database.txt
01fffca9-05c8-41a9-8539-8bb2f587cef2
02fffd0d-fbcf-4759-9478-cfd32c987101
03fffd54-8d62-4555-a4ce-370f061048d5
04fffdb6-24f9-4b98-865f-ce32bc44872c
05fffe0c-2b9d-47fa-8ee9-2d20d0b28334
06fffea1-46f2-4aa2-93b9-be627189e38b
10ffff8a-cc20-4a2b-b9b2-a3cbc2000e49
11ffffaf-fd54-49f3-9719-4a63690430d9
12ffffc6-4ea8-4336-bdf1-e2d9d71a1c29

$ cat disk.txt
01fffca9-05c8-41a9-8539-8bb2f587cef2
02fffd0d-fbcf-4759-9478-cfd32c987101
03fffd54-8d62-4555-a4ce-370f061048d5
04fffdb6-24f9-4b98-865f-ce32bc44872c
05fffe0c-2b9d-47fa-8ee9-2d20d0b28334
06fffea1-46f2-4aa2-93b9-be627189e38b
07fffeed-5a0b-41f8-86cd-e6d99834c187
08ffff24-fb12-488c-87eb-1a07072fc706
09ffff29-ba3d-4582-8ce2-80b47ed927d1
10ffff8a-cc20-4a2b-b9b2-a3cbc2000e49

我試圖完成的是為差異創建文件。

  1. disk.txt 中具有唯一性的文件(因此我可以從磁盤中刪除它們)
  2. 在 database.txt 中具有唯一性的文件(所以我可以從備份和恢復中檢索它們)

使用comm檢索差異

我用comm來查看兩個文件之間的差異。 可悲的是, comm在一些唯一性之后也會返回重復項。

$ comm -13 database.txt disk.txt
07fffeed-5a0b-41f8-86cd-e6d99834c187
08ffff24-fb12-488c-87eb-1a07072fc706
09ffff29-ba3d-4582-8ce2-80b47ed927d1
10ffff8a-cc20-4a2b-b9b2-a3cbc2000e49
$ comm -13 database.txt disk.txt
07fffeed-5a0b-41f8-86cd-e6d99834c187
08ffff24-fb12-488c-87eb-1a07072fc706
09ffff29-ba3d-4582-8ce2-80b47ed927d1
10ffff8a-cc20-4a2b-b9b2-a3cbc2000e49

在這些大文件之一上使用comm需要 28,38 秒。 這真的很快,但不是一個解決方案。

使用fgrepcomm結果中刪除重復項

我可以使用fgrepcomm結果中刪除重復項,這適用於示例。

$ fgrep -vf duplicate-plus-uniq-disk.txt duplicate-plus-uniq-database.txt
11ffffaf-fd54-49f3-9719-4a63690430d9
12ffffc6-4ea8-4336-bdf1-e2d9d71a1c29
$ fgrep -vf duplicate-plus-uniq-database.txt duplicate-plus-uniq-disk.txt
07fffeed-5a0b-41f8-86cd-e6d99834c187
08ffff24-fb12-488c-87eb-1a07072fc706
09ffff29-ba3d-4582-8ce2-80b47ed927d1

在大文件上,這個腳本在一段時間后就崩潰了。 所以這不是解決我的問題的可行選擇。

使用 python difflib獲取唯一性

我嘗試使用從BigSpicyPotato 在另一篇文章的回答中獲得的這個 python 腳本

import difflib
with open(r'disk.txt','r') as masterdata:
    with open(r'database.txt','r') as useddata:
        with open(r'uniq-disk.txt','w+') as Newdata:
            usedfile = [ x.strip('\n') for x in list(useddata) ]
            masterfile = [ x.strip('\n') for x in list(masterdata) ]

            for line in masterfile:
                if line not in usedfile:
                    Newdata.write(line + '\n')

這也適用於示例。 目前這仍在運行並占用了我的 CPU 資源。看看 uniq-disk 文件,它也很慢。

問題

我可以在 bash / python 中嘗試任何更快/更好的選擇嗎? 我也在研究awk / sed以解析結果表單comm

來自man comm*由我添加:

Compare **sorted** files FILE1 and FILE2 line by line.

您必須對comm的文件進行排序。

sort database.txt > database_sorted.txt
sort disk.txt > disk_sorted.txt
comm -13 database_sorted.txt disk_sorted.txt

請參閱man sort以了解各種速度和內存增強選項,例如--batch-size 、 --temporary --temporary-directory --buffer-size --parallel

disk.txt 中具有唯一性的文件
在 database.txt 中具有唯一性的文件

排序后,您可以實現您的 python 程序,該程序逐行比較文件並寫入提到的文件,就像帶有自定義輸出的comm一樣。 不要將整個文件存儲在內存中。

您還可以使用joincomm --output-delimiter=' '執行此操作:

join -v1 -v2 -o 1.1,2.1 disk_sorted.txt database_sorted.txt | tee >(
    cut -d' ' -f1 | grep -v '^$' > unique_in_disk.txt) |
    cut -d' ' -f2 | grep -v '^$' > unique_in_database.txt

comm正是我需要的。 我的 disk.txt 文件的第 10 行后面有一個空格。 因此 comm 將其作為唯一字符串返回。 請查看@KamilCuk 答案以獲取有關排序文件和使用通訊的更多上下文。

 # WHINY_USERS=1 isn't trying to insult anyone - 
 # it's a special shell variable recognized by 
 # mawk-1 to presort the results

 WHINY_USERS=1 {m,g}awk '

 function phr(_) { 
    print \
          "\n Uniques for file : { "\
     (_)" } \n\n -----------------\n" 
 } 
 BEGIN {
          split(_,____) 
        split(_,______) 
     PROCINFO["sorted_in"] = "@val_num_asc"
                        FS = "^$"
 } FNR==NF {
    ______[++_____]=FILENAME 
 }       {
      if($_ in ____) { 
          delete ____[$_] 
      } else {
          ____[$_]=_____ ":" NR 
      }
 } END  { 
    for(__ in ______) { 
         phr(______[__])
             _____=_<_
         for(_ in ____) {
             if(+(___=____[_])==+__) {
                 print "  ",++_____,_,
                       "(line "(substr(___,
                       index(___,":")+!!__))")" 
     }   }   }
 printf("\n\n") } ' testfile_disk.txt testfile_database.txt 

|

 Uniques for file : { testfile_disk.txt } 

 -----------------

   1 07fffeed-5a0b-41f8-86cd-e6d99834c187 (line 7)
   2 08ffff24-fb12-488c-87eb-1a07072fc706 (line 8)
   3 09ffff29-ba3d-4582-8ce2-80b47ed927d1 (line 9)

 Uniques for file : { testfile_database.txt } 

 -----------------

   1 11ffffaf-fd54-49f3-9719-4a63690430d9 (line 18)
   2 12ffffc6-4ea8-4336-bdf1-e2d9d71a1c29 (line 19)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM