join
join 是 paste 的一个很好的增强版本。join 只有在所要连接的文件共享某个共同的域时才会工作。
举例来说,考虑我们上面介绍 paste 时所使用的两个文件。下面是在使用 join 对其进行合并时所发生的事情:
# join fileone filetwo
注意这并没有显示任何东西。join 工具必须要在所操作的文件之间找到共同的域,默认情况下,它期望这个共同的域就是第一个域。
要了解这是如何工作的,我们可以尝试添加一些新内容。假设 fileone 现在包含以下内容:
aaaa Jurassic Park
bbbb AI
cccc The Ring
dddd The Mummy
eeee Titanic
filetwo 现在包含以下内容:
aaaa Neil 1111
bbbb Steven 2222
cccc Naomi 3333
dddd Brendan 4444
eeee Kate 5555
现在,再次尝试下面的命令:
# join fileone filetwo
aaaa Jurassic Park Neil 1111
bbbb AI Steven 2222
cccc The Ring Naomi 3333
dddd The Mummy Brendan 4444
eeee Titanic Kate 5555
此时第一个域相同的地方就会被识别出来,匹配项也就进行了合并。paste 是盲目地从每个文件中提取内容并创建输出结果;而 join 则是只合并那些匹配的行,这种匹配必须非常精确。举例来说,假设您向 filetwo 文件中添加一行内容:
aaaa Neil 1111
bbbb Steven 2222
ffff Elisha 6666
cccc Naomi 3333
dddd Brendan 4444
eeee Kate 5555
现在这个命令只会产生下面的输出结果了:
# join fileone filetwo
aaaa Jurassic Park Neil 1111
bbbb AI Steven 2222
只要这两个文件不再匹配了,就不会再执行任何操作了。第一个文件的每一行都匹配且只匹配于第二个文件相同行的默认域。如果找到匹配项,它们就会组成输出;否则就不再执行任何操作了。
默认情况下,join 只会查找第一个域进行匹配,并输出所有列的内容;不过我们可以对这种行为进行修改。-1 选项让我们可以指定使用哪个域作为 fileone 中的匹配项, -2 选项让我们可以指定使用哪个域作为 filetwo 中的匹配项。
举例来说,要对 fileone 的第二个域和 filetwo 的第三个域进行匹配,我们可以使用下面的语法:
# join -1 2 -2 3 fileone filetwo
-o 选项可以以 {file.field} 格式来指定输出结果。因此,要在匹配行上打印 fileone 的第二个域和 filetwo 的第三个域,语法为:
# join -o 1.2 -o 2.3 fileone filetwo
join:一个实际的例子
在实践中可以使用 join 工具最明显的方法是从 /etc/passwd 中提取用户名和对应的主目录项,并从 /etc/group 文件中提取组名。组名在 /etc/passwd 文件中是以数字的格式出现在第四个域中的。类似地,它们在 /etc/group 文件中是在第三个域中出现的。
# join -1 4 -2 3 -o 1.1 -o 2.1 -o 1.6 -t":" /etc/passwd /etc/grouproot:root:/root
bin:bin:/bin
daemon:daemon:/sbin
adm:adm:/var/adm
lp:lp:/var/spool/lpd
nobody:nobody:/
vcsa:vcsa:/dev
rpm:rpm:/var/lib/rpm
nscd:nscd:/
ident:ident:/home/ident
netdump:netdump:/var/crash
sshd:sshd:/var/empty/sshd
rpc:rpc:/