join / awk:在列上加入2个文件

时间:2016-01-25 14:08:00

标签: bash join awk

我想加入第二列下面的2个文件。

# cat vmid
10   win7-x64-17   [datastore1]   win7-kms-17/win7-template_1.vmx   windows7_64Guest   vmx-08
11   win7-x64-18   [datastore1]   win7-kms-18/win7-template_1.vmx   windows7_64Guest   vmx-08
4   win7-x64-11   [datastore1]   win7-kms-11/win7-template_1.vmx   windows7_64Guest   vmx-08
5   win7-x64-12   [datastore1]   win7-kms-12/win7-template_1.vmx   windows7_64Guest   vmx-08
6   win7-x64-13   [datastore1]   win7-kms-13/win7-template_1.vmx   windows7_64Guest   vmx-08
7   win7-x64-14   [datastore1]   win7-kms-14/win7-template_1.vmx   windows7_64Guest   vmx-08
8   win7-x64-15   [datastore1]   win7-kms-15/win7-template_1.vmx   windows7_64Guest   vmx-08
9   win7-x64-16   [datastore1]   win7-kms-16/win7-template_1.vmx   windows7_64Guest   vmx-08

# cat mac
00:0c:29:2f:00:d8   win7-kms-11
00:0c:29:db:f1:15   win7-kms-12
00:0c:29:ca:a3:d3   win7-kms-13
00:0c:29:f1:5e:ef   win7-kms-14
00:0c:29:1a:55:a6   win7-kms-15
00:0c:29:77:2e:93   win7-kms-16
00:0c:29:ae:5f:7f   win7-kms-17
00:0c:29:20:b4:aa   win7-kms-18

预期输出(未分类,无后顾之忧):

10  win7-x64-17     00:0c:29:ae:5f:7f
11  win7-x64-18     00:0c:29:20:b4:aa
4  win7-x64-11      00:0c:29:2f:00:d8
5  win7-x64-12      00:0c:29:db:f1:15
6  win7-x64-13      00:0c:29:ca:a3:d3
7  win7-x64-14      00:0c:29:f1:5e:ef
8  win7-x64-15      00:0c:29:1a:55:a6
9  win7-x64-16      00:0c:29:77:2e:93

以下是我的2次尝试。 两者都不返回

# awk 'NR==FNR {a[$2]=$1;next } ($2 in a) {print $2" "a[$2]" "$1 }' vmid mac
# join -j 2 <(sort -k 2 vmid) <(sort -k 2 mac)

我知道我的命令工作正常,因为当我在测试输入上尝试时,上述命令都按预期工作,如下所示:

# cat f1
82  d   
83  r
10  k
12  s

# cat f2
m   r
b   d
p   k
p   s

# join -j 2 <(sort -k 2 f1) <(sort -k 2 f2)
d 82  b
k 10 p
r 83 m
s 12 p

# awk 'NR==FNR {a[$2]=$1;next } ($2 in a) {print $2" "a[$2]" "$1 }' f1 f2 
r 83 m
d 82 b
k 10 p
s 12 p

任何指针都会非常有用。

感谢。

3 个答案:

答案 0 :(得分:2)

使用join,您可以使用以下命令:

join -1 4 -2 2 <(tr '/' ' ' <vmid | sort -k4) <(sort -k2 mac) | cut -d' ' -f1,2,8

说明:

join -1 4 -2 2根据第一个输入文件的列4和第二个输入文件的列2加入输入文件。

但是,join期望按列排序的文件按预期工作。此外,我们需要将win7-kms-1win7-kms-1/win7-template_1.vmx分开,即将/替换为空格,以便将其作为单独的列呈现给join。您可以在致电join之前准备相关文件,但也可以使用process substitution(如我所示)。

最后,我使用cut仅选择感兴趣的列。

目前为止join命令。我想解释一下。解决您的用例的另一种方法是使用您已经提到的awk。其实我会建议。

你差不多了,但应该是:

awk -F'[[:space:]/]+' 'NR==FNR{s[$4]=$1;next}$2 in s{print s[$2],$2,$1}' vmid mac

我使用一个或多个空格或/字符来分隔字段。这样,您就可以轻松访问字段win7-kms-1中的$4

只要总行数等于当前文件中的行号,

NR == FNR就为真。实际上,只要我们读取第一个输入文件,这才是真的。我们使用它来创建vmid的查找表,并根据字段4存储字段。

$2 in s{print s[$2],$2,$1}然后检查mac行是否出现在查找中并打印出那种情况下感兴趣的值。

答案 1 :(得分:1)

使用awk(假设单词总是kms和x64):

awk 'NR==FNR{sub("kms","x64",$2);a[$2]=$1;next}{print $1 ,$2,a[$2];}' mac vmid

答案 2 :(得分:0)

这样的事情(在perl中):

\d{2}:

当在命令行或通过stdin提供文件名时,这将起作用。

  • 逐行迭代
  • 如果它以%mac_lookup开头,则认为它是mac-&gt;主机对,并插入10 win7-x64-17 00:0c:29:ae:5f:7f 11 win7-x64-18 00:0c:29:20:b4:aa 4 win7-x64-11 00:0c:29:2f:00:d8 5 win7-x64-12 00:0c:29:db:f1:15 6 win7-x64-13 00:0c:29:ca:a3:d3 7 win7-x64-14 00:0c:29:f1:5e:ef 8 win7-x64-15 00:0c:29:1a:55:a6 9 win7-x64-16 00:0c:29:77:2e:93
  • 否则假设它是一条数据线
  • 从第4个字段中提取密钥(数组从perl中的0开始)
  • 使用该密钥从哈希中读取。

,并提供:

perl -lane 'if($F[0] =~ m/^\d{2}:/){$M{$F[1]}=$F[0]}else{print join "\t", @F[0,1], $M{$F[3]=~s|/.*||r},"\n"}'

注意 - 订单将匹配文件顺序,而不是排序。

如果需要,这会崩溃到一个班轮(虽然IMO通常不是一件好事 - 你很难读懂结果)。

#navcontainer #navbar {
width: 600px; // change this to a width that suits your menu
height: 51px;
line-height:50px;
margin-left: auto;
margin-right: auto;
margin-top: 1px;
}