我有一个table_1
A D G
B E H
C F I
awk '{print $1}' table_1
我使用以下命令打印上表的第 1 列:list_1
A
B
C
我想用list_1
上面的 to grep -f
fromtable_2
A n m
B m n
C n m
D m n
E n m
要得到table_3
A n m
B m n
C n m
但我想使用单行代码来完成此操作,而不需要保存list_1
.
我该如何构建命令?
答案1
一个微不足道的(但是不是bash 特定的)变化赛勒斯的评论:
awk '{print $1}' table_1 | grep -f - table_2
它使用广泛的约定,即文件名-
意思是“从标准输入读取”。
答案2
使用awk
:
awk 'NR==FNR{a[$1];next} ($1 in a)' table_1 table_2
答案3
这是另一种使用方法join
。如果文件已排序,并且table_2
实际上只有三列,您可以使用
join -o "2.1 2.2 2.3" table_1 table_2 > table_3
作为库萨拉南达 说是
join
一个专门用于通过将第一个文件的一列中的值与第二个文件的一列中的值进行匹配来组合两个文件的程序。默认情况下,如果使用每个文件的第一列(您可以覆盖它)。默认情况下,它组合匹配的行,如下所示:
$ join table_1 table_2
A D G n m
B E H m n
C F I n m
上面-o "2.1 2.2 2.3"
说“输出第二个文件的第一个字段,然后是第二个文件的第二个字段,然后是第二个文件的前三分之一(但第一个文件1中没有任何内容)”。不幸的是,这里似乎没有任何快捷方式、简写、加速器或通配符;没有办法说“从第二个文件输出整行”。如果第二个文件有很多字段,则-o
格式必须很长。
这与基于 - 的解决方案不同grep
(您的和矿),因为它专门将 的第 1 列中的值table_1
与 的第 1 列中的值进行匹配table_2
,并且不会为您提供第 2 列或第 3 列中的行,或者第 1 列中的行。table_2
与一样 ,识别( )选项,因此,如果 的第一行是(带有小写的),当(且仅当)您指定 时,您将在输出中得到该行。 ________ 1第一个文件的第一个字段除外——它与第二个文件的第一个字段相同。A
AZ
join
grep
-i
--ignore-case
table_2
a n m
a
table_3
-i
答案4
bash
假设两个表都在第一列上排序,并使用类似或的shellksh93
来理解进程替换<(...)
:
$ join <( awk '{ print $1 }' table_1 ) table_2
A n m
B m n
C n m
如果表是不是排序后,我们需要对它们进行排序:
$ join <( awk '{ print $1 }' table_1 | sort ) <( sort table_2 )
A n m
B m n
C n m
该join
实用程序执行关系型 INNER JOIN 操作在您提供的两个文件的第一列(默认情况下)。
将输出重定向到要创建的新文件table_3
:
$ join <( awk '{ print $1 }' table_1 | sort ) <( sort table_2 ) >table_3