как объединить два файла с awk? - PullRequest
4 голосов
/ 09 марта 2012

У меня есть два файла в одном порядке, и они имеют одинаковое количество строк:

file1 (только 2 столбца):

562_201 RIR1
562_202 RIR1
562_203 RIR1
562_204 RIR1
562_205 RIR1
562_206 RIR1
562_207 RIR1
562_208 RIR1
562_209 RIR1
562_210 WR1 
562_211 WR1 
562_212 WR1 

file2 (я должен сказать, что file2имеет более миллиона строк!):

562_201 0101
562_202 0101
562_203 0101
562_204 0101
562_205 0101
562_206 0101
562_207 0101
562_208 0101
562_209 0101
562_210 0101
562_211 0101
562_212 0101

и я хочу объединить их, чтобы получить:

562_201 RIR1 0101
562_202 RIR1 0101
562_203 RIR1 0101
562_204 RIR1 0101
562_205 RIR1 0101
562_206 RIR1 0101
562_207 RIR1 0101
562_208 RIR1 0101
562_209 RIR1 0101
562_210 WR1  0101
562_211 WR1  0101
562_212 WR1  0101

спасибо!

Ответы [ 4 ]

10 голосов
/ 09 марта 2012

Вы можете использовать команду join:

$ join file1.txt file2.txt
6 голосов
/ 09 марта 2012

Я не уверен, но команда join может загрузить оба файла в память.Это может быть проблематично, если один или оба файла огромны.

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

#!/usr/bin/awk -f

# Load file1 into an array...
BEGIN {
  while (getline < "file1") {
    file1[$1]=$0;
  }
}

{
  key=$1;    # Store the key
  $1="";     # Blank the key (now $0 starts with the field separator)
  print file1[key] $0;
}

Использование:

[ghoti@pc ~/tmp]$ ./join.awk file2
562_201 RIR1 0101
562_202 RIR1 0101
562_203 RIR1 0101
562_204 RIR1 0101
562_205 RIR1 0101
562_206 RIR1 0101
562_207 RIR1 0101
562_208 RIR1 0101
562_209 RIR1 0101
562_210 WR1 0101
562_211 WR1 0101
562_212 WR1 0101

Как предложил Гленн, нотация:

awk 'NR==FNR {file1[$1]=$0; next} {$1=file1[$1]; print}' file1 file2

- это более классический подход к той же идее загрузки первого файла в массив.

Если эти файлы с миллионами строк слишком велики для хранения в памяти, вы также можете пройти по каждому файлу в отдельном канале, загружая только одну строку за раз из каждого файла в память:

$ awk '{getline line < "file1"; print line,$2}' file2

Это читает строки в файле2, и для каждой строки также читает строку из файла1 в переменную, а затем печатает переменную и дополнительное поле из файла2.В памяти хранится только одна строка за раз.

Как есть, предполагается, что первое поле всегда совпадает в каждом файле, то есть проверка ошибок отсутствует.Если вы хотите что-то, это достаточно просто реализовать:

$ awk '{getline line < "file1"; split(line,a); if(a[1]!=$1) {exit(1)} print line,$2}' file2

Это завершится со статусом выхода 1, если $1 не совпадает.

5 голосов
/ 09 марта 2012

AWK

awk 'NR==FNR{a[$1]=$2;next;}gsub($1,$1" "a[$1])' file1 file2
2 голосов
/ 26 января 2015
paste file1 file2 | awk '{$3=""; print}'

Объяснение:

  1. paste f1 f2: объединить строку за строкой
  2. $3=""; print: удалить повторяющийся столбец
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...