Linux文本处理工具之join,paste

大纲

1、join是什么?有什么作用?

2、join语法格式

3、实战演练

4、引入paste命令



1、join是什么?有什么作用?

    Linux下最常用的数据文件格式是文本格式的,使用分隔符来区分不同的字段,比如冒号(:)、制表符、空格等。像常见的/etc/passwd和 /etc/group两个文件就是用":"来分隔的。这种文本格式我们可以视为文本数据库,既方便人去阅读,也适合程序处理,通常某列类似于数据库中的关键字。

    join命令就是一个根据关键字合并数据文件的命令(join lines of two files on a common field),类似于关系型数据库中两张表关联查询。

    有过关系型数据库使用经验的同学都应该知道,当我们组合多个表进行查询时,通常要指定表之间如何关联的条件,否则产生笛卡尔积。下例展示了如何通过 CategoryID字段联接 Categories和 Products表:

SELECT CategoryName, ProductName
FROM Categories INNER JOIN Products
ON Categories.CategoryID = Products.CategoryID;


    如果了解关系型数据库的关联查询,那么join命令的工作原理很容易理解。


2、join语法格式

    语法我们可以通过 join --help 命令查看:

Usage: join [OPTION]... FILE1 FILE2
For each pair of input lines with identical join fields, write a line to
standard output.  The default join field is the first, delimited
by whitespace.  When FILE1 or FILE2 (not both) is -, read standard input.

  -a FILENUM        also print unpairable lines from file FILENUM, where
                      FILENUM is 1 or 2, corresponding to FILE1 or FILE2
  -e EMPTY          replace missing input fields with EMPTY
  -i, --ignore-case  ignore differences in case when comparing fields
  -j FIELD          equivalent to ‘-1 FIELD -2 FIELD‘
  -o FORMAT         obey FORMAT while constructing output line
  -t CHAR           use CHAR as input and output field separator
  -v FILENUM        like -a FILENUM, but suppress joined output lines
  -1 FIELD          join on this FIELD of file 1
  -2 FIELD          join on this FIELD of file 2

    帮助文档这样说到:

“For each pair of input lines with identical join fields, write a line to standard output.  The default join field is the first, delimited by whitespace.  When FILE1 or FILE2 (not both) is -, read standard input.”

join根据公共字段(关键字)来合并两个文件的数据行,然后送到标准输出。默认以空白(whitespace)分隔数据,并且默认比对第一个字段。

常用的有以下几个选项:

-t CHAR

指定分隔符,比如 -t‘:‘则使用:作为分隔符,默认分隔符为空白[空格+TAB+换行](whitespace)。

-1 FIELD

指定第1个文件使用哪一个字段进行Join

-2 FIELD

指定第2个文件使用哪一个字段进行join

-a FILENUM

相当于OUTER JOIN

-o <FILENO.FIELDNO> ...

其中FILENO=1表示第1个文件,FILENO=2表示第2个文件,FIELDNO表示字段序号,从1开始编号。默认会全部输出,但关键字列只输出一次。

比如:-o 1.1 1.2 2.2 表示输出第一个文件的第一个字段、第二个字段,第二个文件的第二个字段。


join与SQL关联类比:

内连接(inner join)                          格式:join <FILE1> <FILE2>
左连接(left join, 左外连接, left outer join)  格式:join -a1 <FILE1> <FILE2>
右连接(right join, 右外连接,right outer join) 格式:join -a2 <FILE1> <FILE2>
全连接(full join, 全外连接, full outer join)  格式:join -a1 -a2 <FILE1> <FILE2>


3、实战演练

Important: FILE1 and FILE2 must be sorted on the join fields.
需要注意的是:在使用join之前,文件最好使用sort进行排序处理。


准备测试数据:

# head month_en.txt month_zh.txt 
==> month_en.txt <==
1   January
2   February
3   March
14  "Unknown"

==> month_zh.txt <==
1   一月
2   二月
3   三月
13  "十三月,故意的"

a、inner join

    join 没有指定任何参数的情况下,默认使用whitespace作为分隔符,并使用第一个字段作为join关键字,忽略关键字不匹配的行。

# join month_en.txt  month_zh.txt 
1 January 一月
2 February 二月
3 March 三月


b、左外连接(left outer join)

join -a1 month_en.txt  month_zh.txt 
1 January 一月
2 February 二月
3 March 三月
14 "Unknown"

这次把"14 Unknown"这一行也显示出来了,也就是说把month_en.txt中不匹配的行也显示出来。


c、右外连接(right outer join)

# join -a2 month_en.txt  month_zh.txt 
1 January 一月
2 February 二月
3 March 三月
13 "十三月,故意的"

这次显示”十三月,故意的”这一行显示出来,也就是把month_zh.txt不匹配的行显示出来。


d、全连接(full join)

# join -a1 -a2 month_en.txt  month_zh.txt 
1 January 一月
2 February 二月
3 March 三月
13 "十三月,故意的"
14 "Unknown"

看到了吧,效果是很明显的。


e、指定分隔符

我们把/etc/passwd和/etc/shadow整合起来。

# head -n3 /etc/passwd /etc/shadow
[sudo] password for yy: 
==> /etc/passwd <==
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin

==> /etc/shadow <==
root:!:16212:0:99999:7:::
daemon:*:16177:0:99999:7:::
bin:*:16177:0:99999:7:::

我们看到,这两个文件都是以":"作为分隔符,我们以第一个字段作为join关键字

# join -t: /etc/passwd /etc/shadow
root:x:0:0:root:/root:/bin/bash:!:16212:0:99999:7:::
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin:*:16177:0:99999:7:::
bin:x:2:2:bin:/bin:/usr/sbin/nologin:*:16177:0:99999:7:::

OK, 看到了吧,是不是非常方便。这里主要是用到SQL联合查询的概念。


4、引入paste命令

    paste有什么作用呢?paste仅仅简单的把两个文件的行粘在一起,构成新行的字段默认以TAB分隔。它相比与join命令就简单得多了,join命令必须根据两个文件相关联的关键字,然后再进行合并,而paste什么都不考虑,直接进行合并。

# paste month_en.txt month_zh.txt 
1   January     1   一月
2   February    2   二月
3   March       3   三月
14  "Unknown"   13  "十三月,故意的"

看出paste和join的差别了吗?当然,可以使用-d选项指定构成新行的分隔符。


本文出自 “Share your knowledge” 博客,请务必保留此出处http://skypegnu1.blog.51cto.com/8991766/1427158

Linux文本处理工具之join,paste,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。