这与Bash 脚本中解决的从多个 CSV 文件中查找匹配行的问题非常相似。它不完全相同,但非常相似。(非常相似,我只需要删除三个sort
命令,sed
稍微更改三个命令,更改文件名,将 'missing' 值从更改no
为0
,并将最后的替换sed
从逗号更改为空格。)
join
带有sed
(通常sort
也是,但数据已经充分排序)的命令是需要的主要工具。假设:
没有出现在原始数据中。为了记录文件中一行的存在,我们需要文件中的一个1
字段(它几乎在那里);当没有匹配时,我们将join
提供。每个非标题行的末尾需要变成0
,标题中的最后一个字段也需要在前面加上。然后,使用的进程替换,我们可以编写:1
:1
:
bash
$ sed 's/[ ]\([^ ]*\)$/:\1/' file1 |
> join -t: -a 1 -a 2 -e 0 -o 0,1.2,2.2 - <(sed 's/[ ]\([^ ]*\)$/:\1/' file2) |
> join -t: -a 1 -a 2 -e 0 -o 0,1.2,1.3,2.2 - <(sed 's/[ ]\([^ ]*\)$/:\1/' file3) |
> sed 's/:/ /g'
id name in1 in2 in3
1 jon 1 0 0
2 sue 1 1 1
3 adam 0 0 1
3 bob 0 1 0
$
该sed
命令(三次):
在文件的每一行的最后一个字段之前添加。连接非常接近对称。-t:
指定字段分隔符是冒号;-a 1
and表示当文件中-a 2
没有匹配项时,该行仍将包含在输出中;这-e 0
意味着如果文件中没有匹配项,0
则在输出中生成 a;并且该-o
选项指定输出列。对于第一个连接,-o 0,1.2,2.2
输出是连接列 (0),然后是1
两个文件中的第二列 (the )。第二个连接在输入中有 3 列,因此它指定-o 0,1.2,1.3,2.2
. 该参数-
本身的意思是“读取标准输入”。这<(...)
符号是“进程替换”,其中文件名(通常/dev/fd/NN
)提供给连接命令,它包含括号内的命令输出。然后再次过滤输出sed
以用空格替换冒号,从而产生所需的输出。
与所需输出的唯一区别是3 bob
after的排序3 adam
;目前还不清楚您在所需输出中反向订购它们的依据是什么。如果它很重要,可以设计一种方法来以不同的方式解决顺序(例如sort -k1,1 -k3,5
,除了将标签行排序在数据之后;如有必要,有解决方法)。