【问题标题】:Comparing many files in Bash比较 Bash 中的许多文件
【发布时间】:2012-05-01 13:20:49
【问题描述】:

我正在尝试自动执行一项我通常手动完成的工作任务,即从多个用户的权限中获取数据库输出并比较它们以查看它们的共同点。我现在有一个使用 comm 和 paste 的脚本,但它并没有提供我想要的所有输出。

部分问题在于 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 和 Internet 的情况下,三分之二拥有销售记录访问权限和 S:驱动权限,每个人中只有一个拥有 Novell 和定价访问权限。

有人可以帮我解决我所缺少的吗?

【问题讨论】:

    标签: bash shell comm


    【解决方案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”到“user3”,这样效果很好),您可以像这样运行它:

    $ ./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(),因此它应该适用于非 GNU 版本的 AWK。缺点是行和列的顺序不可预测。

    #!/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")
        }
    }
    

    【讨论】:

    • 我回家后一定要试试这个。显然,该脚本中有一些内容,但我对 awk 的了解不足以使其正常工作。对我来说它说: awk: ./coorelate: line 35: function asort never defined awk: ./coorelate: line 35: function asort never defined
    • @freehunter:这意味着你有一个非 GNU AWK(不是gawk)。我会发布一个不需要asort() 的版本,我会尽量避免其他傻瓜。
    • 感谢丹尼斯,这非常有效。我想我该是学习 AWK 或 Perl 的时候了,这样我就可以自己做这件事了。
    【解决方案2】:

    您可以使用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
    

    这会让你更接近你正在寻找的东西吗?

    【讨论】:

    • 我实际上是用 diff3 写了一个脚本,直到我遇到一个老板说“现在比较这四个用户!”
    【解决方案3】:

    我会使用 strings 命令从文件中删除任何二进制文件,将它们放在一起,然后在连接的文件上使用 uniq -c 来获取字符串的出现次数

    【讨论】:

    • +1,但您应该在uniq -c 之前对分类输出进行排序。最简单的形式是:sort User? | uniq -c
    • 啊,是的,我总是忘记先提到排序,因为在过去犯了很多不这样做的错误之后使用 uniq 时,这几乎是习惯的力量
    猜你喜欢
    • 2014-11-11
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多