Вставка столбцов UNIX и вставка нулей вместо всех отсутствующих значений

Вставка столбцов UNIX и вставка нулей вместо всех отсутствующих значений

Я хотел бы объединить определенные столбцы из двух текстовых файлов, содержащих разное количество строк, но одинаковое количество столбцов (как показано ниже):

  file1:
  xyz   desc1   12
  uvw   desc2   55
  pqr   desc3   12

  file2:
  xyz   desc1   56
  uvw   desc2   88


  Preferred output:
  xyz   desc1   12  56
  uvw   desc2   55  88
  pqr   desc3   12   0

В настоящее время я использую команду вставки с помощью awk следующим образом:

  paste <(awk '{print $1}' file1) <(awk '{print $2}' file1) <(awk '{print $3}' file1) <(awk '{print $3}' file2) 

Но это, кажется, объединяет только перекрывающиеся столбцы. Есть ли способ в awk вставлять нули вместо пропуска самой строки?

Мне нужно объединить 100 файлов так, чтобы мой выходной файл содержал 102 столбца.

решение1

Если важен порядок столбцов, т.е. числа из одного файла должны храниться в одном столбце, вам нужно добавить заполнение при чтении разных файлов. Вот один из способов, который работает с GNU awk:

слияние.awk

# Set k to be a shorthand for the key
{ k = $1 SUBSEP $2 }

# First element with this key, add zeros to align it with other rows
!(k in h) {
  for(i=1; i<=ARGIND-1; i++)
    h[k] = h[k] OFS 0 
}

# Remember the data element
{ h[k] = h[k] OFS $3 }

# Before moving to the next file, ensure that all rows are aligned
ENDFILE {
  for(k in h) {
    if(split(h[k], a) < ARGIND)
      h[k] = h[k] OFS 0
  }
}

# Print out the collected data
END {
  for(k in h) {
    split(k, a, SUBSEP)
    print a[1], a[2], h[k]
  }
}

Вот несколько тестовых файлов: f1, f2, f3и f4:

$ tail -n+1 f[1-4]
==> f1 <==
xyz desc1 21
uvw desc2 22
pqr desc3 23

==> f2 <==
xyz desc1 56
uvw desc2 57

==> f3 <==
xyz desc1 87
uvw desc2 88

==> f4 <==
xyz desc1 11
uvw desc2 12
pqr desc3 13
stw desc1 14
arg desc2 15

Тест 1

awk -f merge.awk f[1-4] | column -t

Выход:

pqr  desc3  23  0   0   13
uvw  desc2  22  57  88  12
stw  desc1  0   0   0   14
arg  desc2  0   0   0   15
xyz  desc1  21  56  87  11

Тест 2

awk -f merge.awk f2 f3 f4 f1 | column -t

Выход:

pqr  desc3  0   0   13  23
uvw  desc2  57  88  12  22
stw  desc1  0   0   14  0
arg  desc2  0   0   15  0
xyz  desc1  56  87  11  21

Редактировать:

Если выходные данные должны быть разделены табуляцией, установите соответствующий разделитель полей вывода:

awk -f merge.awk OFS='\t' f[1-4]

решение2

Попробуй это:

$ awk '
    FNR == NR { a[$1,$2] = $3; next }
    {
        print $0,(($1,$2) in a) ? a[$1,$2] : "0"
    }
' file2 file1
xyz   desc1   12 56
uvw   desc2   55 88
pqr   desc3   12 0

решение3

Это немного длинно, но работает:

$ cat file1 file2 | awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++} END {for (i in b) max=max<b[i]?b[i]:max; for (i in a) {printf "%s %s", i, a[i]; for (j=b[i]; j<max; j++) printf "%s0", FS  printf "%s", RS}}' 
pqr desc3  12 0
xyz desc1  12 56
uvw desc2  55 88

Блок awk можно отформатировать следующим образом:

awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++}
      END {for (i in b) max=max<b[i]?b[i]:max
          for (i in a) {printf "%s%s%s", i, FS, a[i]
                        for (j=b[i]; j<max; j++) printf "%s0", FS
                        printf "%s", RS}
          }'

Идея состоит в том, чтобы распечатать все файлы, а затем поймать повторяющиеся значения в массиве a[$1 $2]. Также b[$1 $2]содержит количество раз, когда появлялась пара ( $1, ).$2

В END{}блоке мы продолжаем цикл по значениям и дополняем их таким количеством 0элементов, которого не хватает от количества элементов до максимального количества элементов.

Связанный контент