简体   繁体   English

Shell脚本 - 使用特定列上的AWK连接两个文件

[英]Shell script - join two files using the AWK on specific column

I have first file test1.csv separated with pipes and one tab always: 我有第一个文件test1.csv用管道和一个标签分开:

ug|s|B|city|bg1|1|8D|ON-05|100  10|28|288
ug|s|B|city|bg1|1|D9|ON-05|150  11|28|288
ug|s|B|city|bg2|2|94|ON-05|350  12|28|288

I have second file test2.csv only with one tab: 我有第二个文件test2.csv只有一个选项卡:

bg1 250
bg2 350

I want to join them using the column number 5 from the first file (bg1,bg2) so I can take the values from second file (250,350) 我想使用第一个文件(bg1,bg2)中的第5列连接它们,所以我可以从第二个文件中获取值(250,350)

So the final output should be: 所以最终的输出应该是:

ug|s|B|city|bg1|1|8D|ON-05|100|250  10|28|288
ug|s|B|city|bg1|1|D9|ON-05|150|250  11|28|288
ug|s|B|city|bg2|2|94|ON-05|350|350  12|28|288

I tried using the AWK to join them: 我尝试使用AWK加入它们:

awk -F '|' -v OFS='|' '
    FNR==NR {  } {
        split($NF, b, "\t")
        $NF = b[1] FS a[b[1]] "\t" b[2]
    } 1' test2.csv test1.csv > final.csv

but not getting correct results 但没有得到正确的结果

awk '
    BEGIN { FS=OFS="\t"; subFs="|" }
    NR==FNR { map[$1]=$2; next }
    { split($1,subFlds,subFs); print $1 subFs map[subFlds[5]], $2 }
' test2.csv test1.csv
ug|s|B|city|bg1|1|8D|ON-05|100|250      10|28|288
ug|s|B|city|bg1|1|D9|ON-05|150|250      11|28|288
ug|s|B|city|bg2|2|94|ON-05|350|350      12|28|288

This is the perfect use case for my general proposition that -v should be avoided in favor of direct assignment on the command line. 对于我的一般命题,这是一个完美的用例,应该避免使用-v以支持在命令行上直接赋值。 You can easily switch FS between files and do: 您可以轻松地在文件之间切换FS并执行:

$ awk 'NR==FNR{f[$1]=$2; next} {print $0, f[$5]}' test2.csv FS=\| OFS=\| test1.csv
ug|s|B|city|bg1|1|8D|ON-05|100  10|28|288|250
ug|s|B|city|bg1|1|D9|ON-05|150  11|28|288|250
ug|s|B|city|bg2|2|94|ON-05|350  12|28|288|350

This doesn't give you exactly the output you desire, but that's easy enough to fix, albeit a little awkward: 这并没有给你你想要的输出,但这很容易修复,虽然有点尴尬:

awk 'NR==FNR{f[$1]=$2; next} {split($9,a,"\t"); \
    $9=a[1] "|" f[$5] "\t" a[2]}1' test2.csv FS=\| OFS=\| test1.csv

You can do this with Perl also. 您也可以使用Perl执行此操作。

$ cat test2.csv
bg1     250
bg2     350

$ cat test1.csv
ug|s|B|city|bg1|1|8D|ON-05|100  10|28|288
ug|s|B|city|bg1|1|D9|ON-05|150  11|28|288
ug|s|B|city|bg2|2|94|ON-05|350  12|28|288

$ perl -F'\t' -lane 'if($ARGV eq "test2.csv") { $kv{$F[0]}=$F[1]}; if( $ARGV eq "test1.csv" ) { ($x,$y)=(split(/\|/,$F[0]))[4,8]; if($kv{$x}) {$F[0]=~s/$y$/$kv{$x}/g } pr
int "$F[0]\t$F[1]" } ' test2.csv  test1.csv
ug|s|B|city|bg1|1|8D|ON-05|250  10|28|288
ug|s|B|city|bg1|1|D9|ON-05|250  11|28|288
ug|s|B|city|bg2|2|94|ON-05|350  12|28|288

$

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM