Объединение двух текстовых файлов с помощью AWK

Объединение двух текстовых файлов с помощью AWK

У меня нет большого опыта работы с awk, поэтому я пытаюсь преодолеть одну проблему с ним. У меня есть два файла с именами file1.txt и file2.txt. File1.txt:

20 101 1 2 3 4
20 102 5 6 7 8
20 108 3 3 3 3

Файл2.txt:

20 100 99 99 99 99
20 101 11 22 33 44
20 103 55 66 77 88

После первых двух столбцов в каждом из файлов всегда следует 4 значения.

Я пытаюсь объединить эти файлы в один. Я объединяю их по первому и второму столбцам.

В полученном файле должно быть 10 столбцов. Первые два — ключевые, следующие 4 столбца — значения из первого файла, а последние 4 — из второго.

В результирующем файле каждая запись из первого файла, не имеющая соответствия со вторым файлом (и наоборот), будет иметь дополнительные нули, представляющие отсутствующие значения.

Все разделяется пробелами.

Результат должен выглядеть так:

20 100 0 0 0 0 99 99 99 99
20 101 1 2 3 4 11 22 33 44
20 102 5 6 7 8 0 0 0 0
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0

Это мой скрипт awk, который я модифицировал, найдя его в Интернете:

BEGIN {                                                                                                                
   OFS=" "
}                                      
{                               
   i=$1 OFS $2 #Making key out of first and second field of the first file                    
}
   NR==FNR {                             
   A[i]=$0  #Saving records from first file to an array using first two columns as index                           
   next
}
#Next part assumes that I'm reading file2.txt                                         
i in A {                                
   printf "%s",A[i]  #Here, I have a match with first file, and I want to print the joined record I saved from file1.txt                                                                                               
   print $3,$4,$5,$6 #In order to print a joined record, after printing record from first file, I'm printing columns from the second file                                                                                           
   delete A[i]                           
   next
}

{ #Here I print records from file2.txt that don't have a match with file1.txt, and put zeroes to fill missing values
   print 0,0,0,0,$3,$4,$5,$6
}
END { #In the END block I'm printing everything from file1.txt that doesn't have a match and print zeroes aftewards to fill missing values
   for (i in A) {  printf "%s",A[i]; print 0,0,0,0  }                           
}

Результат сортируется по второму столбцу, и все пропущенные значения заполняются нулями. Однако, результат, который я сейчас получаю, выглядит так:

20 100 0 0 0 0 99 99 99 99
11 22 33 443 4
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0
0 0 0 0 6 7 8

Несмотря на то, что файл не отсортирован (я всегда могу использовать sort -k 2), некоторые строки не печатаются так, как я предполагал, и я не могу объяснить, почему он не может нормально вывести элемент массива A. Я пробовал разные вещи, например, временное изменение ORS (вообще никакого вывода) или использование print вместо printf (результат тоже выглядит странно).

Из-за отсутствия опыта возникают дополнительные вопросы:

Разумно ли использовать awk для выполнения этой задачи? Я пробовал использоватьприсоединиться, но в итоге застрял, потому что не смог напечатать столбец с символом новой строки в конце. Может быть, скрипт на Python будет полезнее?

Учитывая, что я буду использовать очень большие файлы для слияния, разумно ли использовать массивы с точки зрения памяти?

Заранее спасибо!

решение1

awk '!second { file1vals[$1 FS $2]=$0 }
      second { print (($1 FS $2 in file1vals)?file1vals[$1 FS $2]: $1 FS $2 FS "0 0 0 0") FS $3, $4, $5, $6;
               delete file1vals[$1 FS $2]
             }
END{ for(x in file1vals) print file1vals[x], "0 0 0 0" }' file1 second=1 file2

это будет работать до тех пор, пока есть достаточно памяти для загрузки первогофайл1в память.

В первом блоке !second {...}, который запускается только тогда, когда это первый файл, и мы загружаемфайл1в связанный массив по паре столбцов 1- го и 2- го в качестве ключей для массива.

Во втором блоке second {...}, который запускается только тогда, когда это второй файл, мы выводим объединенные строки, те, которые имеют совпадающие ключи в обоих файлах, в противном случае мы выводим ключи и нули, а затем остальные столбцы изфайл2; затем мы также удаляем ключи из массива, в delete file1vals[$1 FS $2]котором они существовали в обоих файлах.

В последнем блоке в END мы выводим оставшиеся несовпадающие ключи, относящиеся кфайл1.

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