2012-05-01 90 views
2

我試圖自動執行一項我通常手工完成的任務,即從多個用戶的權限獲取數據庫輸出,並比較它們以查看它們的共同點。我現在有一個使用通訊和粘貼的腳本,但它並沒有給我所有我想要的輸出。比較Bash中的很多文件

問題的一部分出現在comm只處理兩個文件,我需要比較至少三個找到一個趨勢。我還需要確定三者中的兩個是否有共同之處,但第三個沒有它(因此比較兩個comm命令的輸出不起作用)。我需要這些逗號分隔值,以便它可以導入到Excel中。每個用戶都有一個列,最後列出了他們共有的所有內容。如果可以比較兩個以上的文件(並顯示兩比三的比較),comm可以完美工作。

除了代碼,我必須清除原始csv文件中的所有額外髒東西,這是我迄今爲止比較四個用戶的內容。這是非常低效的,但這是我所知道的。

cat foo1 | sort > foo5 
cat foo2 | sort > foo6 
cat foo3 | sort > foo7 
cat foo4 | sort > foo8 

comm foo5 foo6 > foomp 
comm foo7 foo8 > foomp2 

paste foomp foomp2 > output2 
sed 's/[\t]/,/g' output2 > output4.csv 
cat output4.csv 

眼下這個輸出兩個用戶,它們的異同,然後做了另外兩個用戶並將其粘貼在一起一樣。這比手工做得更好,但我知道我可以做更多。

一個例子輸入文件會是這樣的:

用戶1

Active Directory 
Internet 
S: Drive 
Sales Records 

用戶2

Active Directory 
Internet 
Pricing Lookup 
S: Drive 

用戶3

Active Directory 
Internet 
Novell 
Sales Records 

,他們有AD和互聯網中常見的,兩個出o f三個有銷售記錄訪問權限和S:驅動器權限,每個只有一個具有Novell和定價訪問權限。

有人能幫我一下我失蹤的東西嗎?

回答

1

使用GNU AWK(gawk)的發生計數你可以打印顯示多個用戶權限如何關聯的表格。你也可以用任何支持關聯數組(哈希)的語言來做同樣的事情,比如Bash 4,Python,Perl等等。

#!/usr/bin/awk -f 
{ 
    array[FILENAME, $0] = $0 
    perms[$0] = $0 
    if (length($0) > maxplen) { 
     maxplen = length($0) 
    } 
    users[FILENAME] = FILENAME 
} 
END { 
    pcount = asort(perms) 
    ucount = asort(users) 
    maxplen += 2 
    colwidth = 8 
    printf("%*s", maxplen, "") 
    for (u = 1; u <= ucount; u++) { 
     printf("%-*s", colwidth, users[u]) 
    } 
    printf("\n") 

    for (p = 1; p <= pcount; p++) { 
     printf("%-*s", maxplen, perms[p]) 
     for (u = 1; u <= ucount; u++) { 
      if (array[users[u], perms[p]]) { 
       printf("%-*s", colwidth, " X") 
      } else { 
       printf("%-*s", colwidth, "") 
      } 
     } 
    printf("\n") 
    } 
} 

保存此文件,或許稱之爲「關聯」,然後將其設置爲可執行:

$ chmod u+x correlate 

然後,假設文件名對應的用戶名或在其他有意義的(你的例子是「user1」到「用戶3」,這樣效果很好),你可以像這樣運行:

$ ./correlate user* 

,你會根據你的樣品輸入輸出如下:

    user1 user2 user3 
Active Directory X  X  X 
Internet   X  X  X 
Novell        X 
Pricing Lookup    X 
S: Drive   X  X 
Sales Records  X    X 

編輯:

此版本不使用asort(),所以它應該AWK的非GNU版本。缺點是行和列的順序是不可預知的。

#!/usr/bin/awk -f 
{ 
    array[FILENAME, $0] = $0 
    perms[$0] = $0 
    if (length($0) > maxplen) { 
     maxplen = length($0) 
    } 
    users[FILENAME] = FILENAME 
} 
END { 
    maxplen += 2 
    colwidth = 8 
    printf("%*s", maxplen, "") 
    for (u in users) { 
     printf("%-*s", colwidth, u) 
    } 
    printf("\n") 

    for (p in perms) { 
     printf("%-*s", maxplen, p) 
     for (u in users) { 
      if (array[u, p]) { 
       printf("%-*s", colwidth, " X") 
      } else { 
       printf("%-*s", colwidth, "") 
      } 
     } 
    printf("\n") 
    } 
} 
+0

當我回家的時候,我得試試這個。顯然這個腳本里面有些東西,但我不知道awk是否足以讓它正常工作。對我來說它說: awk:./coorelate:第35行:從未定義函數asort awk:./coorelate:第35行:函數asort從未定義 – freehunter

+1

@freehunter:這意味着你有一個非GNU AWK(不是'gawk ')。我會發佈一個不需要'asort()'的版本,我會盡量避免其他gawkisms。 –

+0

謝謝丹尼斯,這個工作很完美。我想它是我學習AWK或Perl的時候,所以我可以自己做。 – freehunter

1

您可以使用diff3程序。從手冊頁:

diff3 - compare three files line by line 

鑑於你的樣品輸入,上面運行diff3結果:

==== 
1:3,4c 
    S: Drive 
    Sales Records 
2:3,4c 
    Pricing Lookup 
    S: Drive 
3:3,4c 
    Novell 
    Sales Records 

這是否讓你更接近你在找什麼?

+0

我其實寫了一個使用diff3的腳本,直到我碰到老闆說「現在比較這四個用戶!」 – freehunter

0

我會用字符串命令從文件一起刪除任何二進制,貓他們再使用的uniq -c在連結文件得到一個字符串

+0

+1,但是您應該在'uniq -c'之前對catted輸出進行排序。最簡單的形式是:'排序用戶? | uniq -c' –

+0

啊是的,我總是忘記提起這種排序,因爲在過去犯這麼多錯誤之後使用uniq的時候,它已經接近習慣的習慣了 –