shell 基于1个文件的第1列与N个文件的第1列的比较进行分析,并基于第1列打印所有文件

r9f1avp5  于 2023-02-05  发布在  Shell
关注(0)|答案(3)|浏览(140)

我有制表符分隔的文件,需要将FILE_1与N(10)个文件进行比较,如果第一个文件的第1列的IDS与其他文件的第1列匹配,则打印文件1和其他文件的值,如果IDS不存在,则将第一个文件和NA添加到其他文件的列中。输入和预期输出文件的示例如下所示。

文件1

A   1.1  0.2    0.3     1.1
B   1.3  2.1    0.2     0.1
C   1.8  0.5    2.6     3.8
D   1.2  5.1    1.7     0.1
E   1.9  4.3    2.8     1.6
F   1.6  5.1    2.9     7.1
G   1.8  2.8    0.3     3.7
H   1.9  3.6    3.7     0.1
I   1.0  2.4    4.9     2.5
J   1.1  2.0    0.1     0.4

文件2

A   d1   Q2    Q.3  E.1
B   a.3  S.1   A.2  R.1
J   a.1  2.0   031  4a4

文件3

E    1d9    4a3  2A8    1D6
F    1a.6   5a1  2W9    7Q1
J    QA8    1.8  0W3    3E7

文件4

F   1aa  5a   2Q    7WQ
G   ac   UW   0QW   3aQ
A   QQ   aws  AW    qw

我已经尝试了下面的代码与两个文件最初,但没有得到预期的输出

awk  '
        FILENAME == "File_2" {
                id = $0
                val[id] = $2","$3","$5
        }
        FILENAME == "File_1" {
                id = $1
                string
                if (val[id] == "") {
                        print id " " "NA"
                } else {
                        print id " " val[id]
                }
        }
' File_2 File_1

上面的代码在每行的末尾打印File_2和NA。
我的预期输出如下所示

最终预期产出

A  1.1  0.2  0.3  1.1  d1   Q2   Q.3  E.1  NA    NA   NA   NA   QQ   aws  AW   qw
B  1.3  2.1  0.2  0.1  a.3  S.1  A.2  R.1  NA    NA   NA   NA   NA   NA   NA   NA
C  1.8  0.5  2.6  3.8  NA   NA   NA   NA   NA    NA   NA   NA   NA   NA   NA   NA
D  1.2  5.1  1.7  0.1  NA   NA   NA   NA   NA    NA   NA   NA   NA   NA   NA   NA
E  1.9  4.3  2.8  1.6  NA   NA   NA   NA   1d9   4a3  2A8  1D6  NA   NA   NA   NA
F  1.6  5.1  2.9  7.1  NA   NA   NA   NA   1a.6  5a1  2W9  7Q1  1aa  5a   2Q   7WQ
G  1.8  2.8  0.3  3.7  NA   NA   NA   NA   NA    NA   NA   NA   ac   UW   0QW  3aQ
H  1.9  3.6  3.7  0.1  NA   NA   NA   NA   NA    NA   NA   NA   NA   NA   NA   NA
I  1.0  2.4  4.9  2.5  NA   NA   NA   NA   NA    NA   NA   NA   NA   NA   NA   NA
J  1.1  2.0  0.1  0.4  a.1  2.0  031  4a4  QA8   1.8  0W3  3E7  NA   NA   NA   NA
jecbmhm3

jecbmhm31#

将GNU awk用于数组的数组ARGINDgensub()

$ cat tst.awk
BEGIN { FS=OFS="\t" }
ARGIND < (ARGC-1) {
    key = $1
    sub("[^"FS"]+"FS"?","")
    fileNrsKeys2vals[ARGIND][key] = $0
    fileNrs2numFlds[ARGIND] = NF
    next
}
{
    printf "%s", $0
    for ( fileNr=1; fileNr<ARGIND; fileNr++ ) {
        if ( fileNr in fileNrs2numFlds ) {
            numFlds = fileNrs2numFlds[fileNr]
            printf "%s", ( $1 in fileNrsKeys2vals[fileNr] ?
                OFS fileNrsKeys2vals[fileNr][$1] :
                gensub(/ /,OFS"NA","g",sprintf("%*s",numFlds,"")) )
        }
    }
    print ""
}
$ awk -f tst.awk file2 file3 file4 file1
A       1.1     0.2     0.3     1.1     d1      Q2      Q.3     E.1     NA      NA      NA      NA      QQ      aws     AW      qw
B       1.3     2.1     0.2     0.1     a.3     S.1     A.2     R.1     NA      NA      NA      NA      NA      NA      NA      NA
C       1.8     0.5     2.6     3.8     NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA
D       1.2     5.1     1.7     0.1     NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA
E       1.9     4.3     2.8     1.6     NA      NA      NA      NA      1d9     4a3     2A8     1D6     NA      NA      NA      NA
F       1.6     5.1     2.9     7.1     NA      NA      NA      NA      1a.6    5a1     2W9     7Q1     1aa     5a      2Q      7WQ
G       1.8     2.8     0.3     3.7     NA      NA      NA      NA      NA      NA      NA      NA      ac      UW      0QW     3aQ
H       1.9     3.6     3.7     0.1     NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA
I       1.0     2.4     4.9     2.5     NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA      NA
J       1.1     2.0     0.1     0.4     a.1     2.0     031     4a4     QA8     1.8     0W3     3E7     NA      NA      NA      NA
bzzcjhmw

bzzcjhmw2#

此解决方案需要“|因为awk数组不能保证是按顺序排列的。它还对紧跟在索引字母后面的空格数(“A”、“B”、“C”等)敏感:

Mac_3.2.57$cat mergeLinesV0.awk
BEGIN {
 i1=1
 i2=1
 i3=1
 i4=1
} NR == FNR {
  ar1[i1]=$0
  i1=i1+1
  f1size=FNR
  next
}{
  f1done=1
} NR-f1size == FNR && f1done {
  ar2[i2]=$0
  i2=i2+1
  f2size=FNR
  next
}{
  f2done=1
} NR-f1size-f2size == FNR && f2done {
  ar3[i3]=$0
  i3=i3+1
  f3size=FNR
  next
}{
  f3done=1
} NR-f1size-f2size-f3size == FNR && f3done {
  ar4[i4]=$0
  i4=i4+1
  f4size=FNR
  next
} END {
  for(i1 in ar1){
    printf("%s   ", ar1[i1])
    found2=0
    for(i2 in ar2){
      if(substr(ar1[i1],1,1)==substr(ar2[i2],1,1)){
        printf("%s   ", substr(ar2[i2],5))
        found2=1
      }
    }
    if(!found2){
      printf("NA   NA   NA   NA   ")
    }
    found3=0
    for(i3 in ar3){
      if(substr(ar1[i1],1,1)==substr(ar3[i3],1,1)){
        printf("%s   ", substr(ar3[i3],5))
        found3=1
      }
    }
    if(!found3){
      printf("NA   NA   NA   NA   ")
    }
    found4=0
    for(i4 in ar4){
      if(substr(ar1[i1],1,1)==substr(ar4[i4],1,1)){
        printf("%s\n", substr(ar4[i4],5))
        found4=1
      }
    }
    if(!found4){
      printf("NA   NA   NA   NA\n")
    }
  }
}
Mac_3.2.57$awk -f mergeLinesV0.awk File1 File2 File3 File4 | sort
A   1.1  0.2    0.3     1.1   d1   Q2    Q.3  E.1   NA   NA   NA   NA   QQ   aws  AW    qw
B   1.3  2.1    0.2     0.1   a.3  S.1   A.2  R.1   NA   NA   NA   NA   NA   NA   NA   NA
C   1.8  0.5    2.6     3.8   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
D   1.2  5.1    1.7     0.1   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
E   1.9  4.3    2.8     1.6   NA   NA   NA   NA   1d9    4a3  2A8    1D6   NA   NA   NA   NA
F   1.6  5.1    2.9     7.1   NA   NA   NA   NA   1a.6   5a1  2W9    7Q1   1aa  5a   2Q    7WQ
G   1.8  2.8    0.3     3.7   NA   NA   NA   NA   NA   NA   NA   NA   ac   UW   0QW   3aQ
H   1.9  3.6    3.7     0.1   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
I   1.0  2.4    4.9     2.5   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
J   1.1  2.0    0.1     0.4   a.1  2.0   031  4a4   QA8    1.8  0W3    3E7   NA   NA   NA   NA
Mac_3.2.57$cat File1
A   1.1  0.2    0.3     1.1
B   1.3  2.1    0.2     0.1
C   1.8  0.5    2.6     3.8
D   1.2  5.1    1.7     0.1
E   1.9  4.3    2.8     1.6
F   1.6  5.1    2.9     7.1
G   1.8  2.8    0.3     3.7
H   1.9  3.6    3.7     0.1
I   1.0  2.4    4.9     2.5
J   1.1  2.0    0.1     0.4
Mac_3.2.57$cat File2
A   d1   Q2    Q.3  E.1
B   a.3  S.1   A.2  R.1
J   a.1  2.0   031  4a4
Mac_3.2.57$cat File3
E   1d9    4a3  2A8    1D6
F   1a.6   5a1  2W9    7Q1
J   QA8    1.8  0W3    3E7
Mac_3.2.57$cat File4
F   1aa  5a   2Q    7WQ
G   ac   UW   0QW   3aQ
A   QQ   aws  AW    qw
Mac_3.2.57$
igetnqfo

igetnqfo3#

给定4个示例文件(如file1.txt .. file4.txt),下面是一个ruby代码:

ruby -lne '
BEGIN{
    files={}
    seen=Set.new()
    data=Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }
}
fields=$_.split(/\t/)
if $<.file.lineno==1; files[$<.file.path]=fields.length-1; end
seen<<fields[0]
data[fields[0]][files.keys.last]=fields[1..]
END{
    seen.each{|k| row=[k]
        files.each{|file, width|
            if data[k][file].empty?
                row.push(*["NA"]*width)
            else 
                row.push(*data[k][file])
            end
        }
        puts row.join("\t")
    }
}'  file?.txt

图纸:

A   1.1 0.2 0.3 1.1 d1  Q2  Q.3 E.1 NA  NA  NA  NA  QQ  aws AW  qw
B   1.3 2.1 0.2 0.1 a.3 S.1 A.2 R.1 NA  NA  NA  NA  NA  NA  NA  NA
C   1.8 0.5 2.6 3.8 NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
D   1.2 5.1 1.7 0.1 NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
E   1.9 4.3 2.8 1.6 NA  NA  NA  NA  1d9 4a3 2A8 1D6 NA  NA  NA  NA
F   1.6 5.1 2.9 7.1 NA  NA  NA  NA  1a.6    5a1 2W9 7Q1 1aa 5a  2Q  7WQ
G   1.8 2.8 0.3 3.7 NA  NA  NA  NA  NA  NA  NA  NA  ac  UW  0QW 3aQ
H   1.9 3.6 3.7 0.1 NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
I   1.0 2.4 4.9 2.5 NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
J   1.1 2.0 0.1 0.4 a.1 2.0 031 4a4 QA8 1.8 0W3 3E7 NA  NA  NA  NA

相关问题