-2

我有三个不同的 CSV 文件。格式如下:

domain1.csv

name1,lastname1
name2,lastname2
name3,lastname3

domain2.csv

name1,lastname1
name6,lastname6
name3,lastname3

domain3.csv

name1,lastname1
name4,lastname4
name3,lastname3

现在基于这三个文件,我需要创建这样的报告

name,lastname,domain1,domain2,domain3
name1,lastname1,yes,yes,yes
name2,lastname2,yes,no,no
name3,lastname3,yes,yes,yes
name4,lastname4,no,no,yes
name6,lastname6,no,yes,no

基本上,此报告只能使用脚本来读取每个文件中的行并在其他两个文件中找到该行并通过匹配名称和姓氏列来创建报告。但我是 shell 脚本的新手。有人能帮我吗。我正在使用 bash。

4

3 回答 3

1

你真的不想用 bash 写这个,意思是while循环和逐行比较,因为这太痛苦而且太慢了。shell 有很多可用的工具。在这种情况下派上用场的一个称为join(关系数据库上下文:这将是笛卡尔积或交叉连接,因为 -a1 -a2)。如果您的 .csv 文件已排序(请参阅 shell 命令sort

join -t, -a1 -a2 dom1.csv dom2.csv

name1,lastname1,lastname1

name2,lastname2

name3,lastname3,lastname3

name6,lastname6

注意第三列。如果该行没有出现在两个文件中,则为空。所以这解决了你一半的问题。然后,您可以根据您的要求尝试使用sedawk更改最后一列,如果它是非空的,是/否。当然,没有什么可以阻止您join再次针对第三个文件运行结果,并按摩输出以包含是/否。

于 2013-07-04T01:08:52.613 回答
1

awk是一种迷你语言,它是大多数类 Unix 操作系统的标准配置,可让您相当轻松地解决此类问题。

awk '{ names[$0] = (names[$0] "," FILENAME) }
     END { print "name,lastname,domain1,domain2,domain3"
           for( elt in names ) {
             printf "%s,%s,%s,%s\n", elt,
                                     index( names[elt], "domain1.csv" ) ? "yes" : "no",
                                     index( names[elt], "domain2.csv" ) ? "yes" : "no",
                                     index( names[elt], "domain3.csv" ) ? "yes" : "no"
           }
         }' domain*.csv | sort

上面的脚本逐行解析每个文件,并使用nameN,lastnameN索引和它们所在的文件名(用逗号分隔)作为值来构造一个关联数组。然后它遍历关联数组并打印每个索引,然后根据数组的值是否包含每个文件名打印“yes”或“no”字符串。

于 2013-07-04T02:06:53.870 回答
0

带有和的join命令是需要的主要工具。假设没有出现在原始数据中。为了记录文件中一行的存在,我们需要文件中的一个字段;当没有匹配时,我们将提供。使用的进程替换,我们可以写:sortsed:yesjoinnobash

$ sed 's/$/:yes/' domain1.csv | sort |
> join -t: -a 1 -a 2 -e no -o 0,1.2,2.2     - <(sed s'/$/:yes/' domain2.csv | sort) |
> join -t: -a 1 -a 2 -e no -o 0,1.2,1.3,2.2 - <(sed 's/$/:yes/' domain3.csv | sort) |
> sed 's/:/,/g'
name1,lastname1,yes,yes,yes
name2,lastname2,yes,no,no
name3,lastname3,yes,yes,yes
name4,lastname4,no,no,yes
name6,lastname6,no,yes,no
$

和组合(三次)将 添加到文件中sed并对名称进行排序。连接非常接近对称。指定字段分隔符是冒号;and表示当文件中没有匹配项时,该行仍将包含在输出中;这意味着如果文件中没有匹配项,则在输出中生成 a;并且该选项指定输出列。对于第一个连接,输出是连接列 ( ),然后是两个文件中的第二列 ( )。第二个连接在输入中有 3 列,因此它指定. 该参数本身的意思是“读取标准输入”。这sort:yes-t:-a 1-a 2-e nono-o-o 0,1.2,2.20yes-o 0,1.2,1.3,2.2-<(...)表示法是“进程替换”,其中/dev/fd/NN向命令提供了文件名(通常是 )join,它在括号内包含命令的输出。然后再次过滤输出sed以用逗号替换冒号,从而产生所需的输出。

于 2013-07-04T01:52:35.953 回答