【问题标题】:Merge two files and transpose rows to columns合并两个文件并将行转置为列
【发布时间】:2018-08-21 23:14:37
【问题描述】:

比较两个文件的第一列。如果匹配,则将同一记录的值从 FILE2 转移到 FILE1。如果没有找到匹配项,填写“NA”

文件1

123 B
124 A
125 N
129 C
134 B
141 T
167 8
179 5

文件2

123 1 1
123 2 1
124 1 3
124 2 3
129 6 1
129 7 1
134 5 1
134 9 1
167 8 2
167 8 2

期望的输出

123 B 1 2 1
124 A 1 2 3
125 N NA
129 C 6 7 1
134 B 5 9 1
141 T NA
167 8 8 8 2
179 5 NA

我已将此代码用于丢失的记录,但我仍然无法为找到的记录转置行:

awk 'NR==FNR{a[$1]=$2;next;}{print $0 "    " ($1 in a ? a[$1] : "NA")}' FILE2 FILE1

123 B    2
124 A    2
125 N    NA
129 C    7
134 B    9
141 T    NA
167 8    8
179 5    NA

提前致谢

【问题讨论】:

  • 请解释如何获得预期输出的第三列。

标签: awk


【解决方案1】:

我假设您要收集 file2 第 2 列的列表,但只保留 file2 第 3 列的最后一个值。

这里有一点perl:

perl -lane '
    if ($. == ++$nr) {
        $x{$F[0]} = $F[1];
    } else {
        push @{ $y{$F[0]} }, $F[1];
        $z{$F[0]} = $F[2];
    }
    close ARGV if eof; # reset $. for new file
    END {
        for $key (sort keys %x) {
            printf "%s %s %s\n", $key, $x{$key},
                (exists $y{$key} ? join(" ", @{$y{$key}}, $z{$key}) : "NA");
        }
    }
' file 1 file2
123 B 1 2 1
124 A 1 2 3
125 N NA
129 C 6 7 1
134 B 5 9 1
141 T NA
167 8 8 8 2
179 5 NA

作为 awk

gawk '
    NR == FNR {
        x[$1] = $2
        next
    }
    {
        y[$1] = y[$1] $2 OFS
        z[$1] = $3
    }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"
        for (key in x) {
            printf "%s %s %s\n", key, x[key], (key in y ? y[key] z[key] : "NA")
        }
    }
' file{1,2}

这仅将 GNU awk 用于 PROCINFO 变量。如果您不想要这种依赖关系,只需删除该行并将输出通过管道传输到| sort -k1,1n

【讨论】:

  • 嗨,格伦,你能不能用 awk 做同样的事情。
  • 你评论的时候我正在翻译。
【解决方案2】:

根据问题中的当前描述和输入示例,此 awk 代码有效:

 awk 'NR==FNR{a[$1]=$2 FS $3 FS $4;next}{print $0,($1 in a?a[$1]:"NA")}' <(awk 'NR%2{printf "%s",$1 FS $2 FS;next}{print $2,$3}' FILE2) FILE1

为了更好的阅读:

 awk 'NR==FNR{a[$1]=$2 FS $3 FS $4;next}
      {print $0,($1 in a?a[$1]:"NA")}' 
<(awk 'NR%2{printf "%s",$1 FS $2 FS;next}{print $2,$3}' FILE2)  
FILE1

使用您的测试数据:

kent$  head f f2
==> f <==
123 B
124 A
125 N
129 C
134 B
141 T
167 8
179 5

==> f2 <==
123 1 1
123 2 1
124 1 3
124 2 3
129 6 1
129 7 1
134 5 1
134 9 1
167 8 2
167 8 2

kent$  awk 'NR==FNR{a[$1]=$2 FS $3 FS $4;next}{print $0,($1 in a?a[$1]:"NA");}' <(awk 'NR%2{printf "%s",$1 FS $2 FS;next}{print $2,$3}' f2) f
123 B 1 2 1
124 A 1 2 3
125 N NA
129 C 6 7 1
134 B 5 9 1
141 T NA
167 8 8 8 2
179 5 NA

【讨论】:

  • 您好,Kent,感谢您的代码。你能解释一下这部分代码吗..
  • @OXXO 您将通过在&lt;(...) 中执行awk one liner 来了解它的作用
【解决方案3】:

请您尝试关注一下。

awk '
FNR==NR{
  if(++b[$1]==1){
    a[$1]=$2
  }
  else{
    a[$1]=a[$1] OFS $2 OFS $3
  }
  next
}
($1 in a){
  print $1,$2,a[$1]
  next
}
{
  print $0,"NA"
}' Input_file2  Input_file1

输出如下。

123 B 1 2 1
124 A 1 2 3
125 N NA
129 C 6 7 1
134 B 5 9 1
141 T NA
167 8 8 8 2
179 5 NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多