Join 使用awk在匹配列值上连接2个文件

Join 使用awk在匹配列值上连接2个文件,join,awk,Join,Awk,我知道有类似的问题张贴,但我仍然有一点麻烦得到我想要的输出使用awk FNR==NR。。。 我有两个这样的文件 File 1: 123|this|is|good 456|this|is|better ... File 2: aaa|123 bbb|456 ... 因此,我想将文件2/column2中的值连接到文件1/column1,并输出文件1(列2,3,4)和文件2(列1) 提前感谢。使用awk,您可以执行以下操作 awk -F \| 'BEGIN { OFS = FS } NR ==

我知道有类似的问题张贴,但我仍然有一点麻烦得到我想要的输出使用awk FNR==NR。。。 我有两个这样的文件

File 1: 
123|this|is|good
456|this|is|better
...

File 2:
aaa|123
bbb|456
...
因此,我想将文件2/column2中的值连接到文件1/column1,并输出文件1(列2,3,4)和文件2(列1)


提前感谢。

使用awk,您可以执行以下操作

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } $1 in val { $(NF + 1) = val[$1]; print }' file2 file1
NF
是记录中的字段数(默认为行),因此
$NF
是最后一个字段,
$(NF+1)
是之后的字段。通过将传递
文件2中保存的值指定给它,在打印记录之前,会将一个新字段追加到记录中

需要注意的一点是:它的行为类似于内部联接,即只打印密钥出现在两个文件中的记录。要使此连接正确,可以使用

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } { $(NF + 1) = val[$1]; print }' file2 file1
也就是说,您可以在追加和打印操作中删除
$1 in val
条件。如果
$1
不在
val
中,
val[$1]
为空,打印前将向记录追加一个空字段

但是使用
join
可能更好:

join -1 1 -2 2 -t \| file1 file2
如果您不想让键字段成为输出的一部分,请通过
cut-d\|-f2-
管道将这些命令中的任何一个的输出去掉,即

join -1 1 -2 2 -t \| file1 file2 | cut -d \| -f 2-

有了awk,你可以做如下事情

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } $1 in val { $(NF + 1) = val[$1]; print }' file2 file1
NF
是记录中的字段数(默认为行),因此
$NF
是最后一个字段,
$(NF+1)
是之后的字段。通过将传递
文件2中保存的值指定给它,在打印记录之前,会将一个新字段追加到记录中

需要注意的一点是:它的行为类似于内部联接,即只打印密钥出现在两个文件中的记录。要使此连接正确,可以使用

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } { $(NF + 1) = val[$1]; print }' file2 file1
也就是说,您可以在追加和打印操作中删除
$1 in val
条件。如果
$1
不在
val
中,
val[$1]
为空,打印前将向记录追加一个空字段

但是使用
join
可能更好:

join -1 1 -2 2 -t \| file1 file2
如果您不想让键字段成为输出的一部分,请通过
cut-d\|-f2-
管道将这些命令中的任何一个的输出去掉,即

join -1 1 -2 2 -t \| file1 file2 | cut -d \| -f 2-

如果文件具有相同顺序的相同行数,则

paste -d '|' file1 file2 | cut -d '|' -f 2-5
我在对Wintermute回答的评论中看到,这些文件没有排序。使用bash,进程替换可以方便地进行动态排序:

paste -d '|' <(sort -t '|' -k 1,1 file1) <(sort -t '|' -k 2,2 file2) |
cut -d '|' -f 2-5

paste-d'|'如果文件具有相同顺序的相同行数,则

paste -d '|' file1 file2 | cut -d '|' -f 2-5
我在对Wintermute回答的评论中看到,这些文件没有排序。使用bash,进程替换可以方便地进行动态排序:

paste -d '|' <(sort -t '|' -k 1,1 file1) <(sort -t '|' -k 2,2 file2) |
cut -d '|' -f 2-5

paste-d'|“您可以避免切割管道,添加连接选项:
-o 1.2,1.3,1.4,2.2
我喜欢使用
$(NF+1)
。通过将if表达式移到大括号外,您可以使它变得更糟糕:
$1 in val{$(NF+1)=val[$1];print}
@glennjackman哦,这是一个很好的观点。不过,我将坚持使用
cut
从输出中删除关键字段;
-o
选项可以解决前面提到的问题,并且有它的优点,但是我觉得
cut
方法的优点是,它可以处理任意多个列,在这里超过了它们。如果说性能是一个问题,事情可能会有所不同。非常感谢!我不能使用join(在这一步),因为这两个文件没有排序。我对$(NF+1)很好奇,因为我是一个awk新手-你能给我一点启发吗?顺便提一下:只有在
file2
中有值的行才会以这种方式打印(本质上,它的行为类似于内部连接)。如果您希望使用空字段打印
file2
中没有值的行,请使用
{$(NF+1)=val[$1]}
而不使用
$1 in val
条件。您可以避免管道切割,添加连接选项:
-o 1.2,1.3,1.4,2.2
我喜欢使用
$(NF+1)
。通过将if表达式移到大括号外,您可以使它变得更糟糕:
$1 in val{$(NF+1)=val[$1];print}
@glennjackman哦,这是一个很好的观点。不过,我将坚持使用
cut
从输出中删除关键字段;
-o
选项可以解决前面提到的问题,并且有它的优点,但是我觉得
cut
方法的优点是,它可以处理任意多个列,在这里超过了它们。如果说性能是一个问题,事情可能会有所不同。非常感谢!我不能使用join(在这一步),因为这两个文件没有排序。我对$(NF+1)很好奇,因为我是一个awk新手-你能给我一点启发吗?顺便提一下:只有在
file2
中有值的行才会以这种方式打印(本质上,它的行为类似于内部连接)。如果希望使用空字段打印
file2
中没有值的行,请使用
{$(NF+1)=val[$1]}
而不使用
$1 in val
条件。