2016-03-14 3 views
0

У меня есть два файла; файл 1:Linux merge files awk command

ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 
ARS-BFGL-BAC-11044 0.9626 688423261 2 01/04/2015 0.9983763305 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 
ARS-BFGL-BAC-11044 0.9926 688423263 2 01/04/2015 0.9983763000 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 

Второй файл, файл 2:

ARS-BFGL-BAC-10975 10 21225382 
ARS-BFGL-BAC-11025 10 84516867 
ARS-BFGL-BAC-11193 1 29303546 

Нужный выход:

ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382 
ARS-BFGL-BAC-11025 0.9992 688423263 1 01/04/2015 0.9983763000 10 84516867 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546 

Так файл 1 имеет гораздо больше строк, чем файл 2. Я только хочу сохраняйте строки на выходе, которые находятся в файле 2 на основе первого столбца, поэтому я хочу, чтобы ARS-BFGL-BAC-10975 повторялось столько раз, сколько в столбце 1, как показано в файле 2, но я не хочу, чтобы ARS-BFGL-BAC-11044 в вывода, поскольку он никогда не появляется в файле 2.

Ближайшее я имею следующую команду awk, но это не позволяет дублировать ARS-BFGL-BAC-10975, то есть я сливаюсь только с длиной файла 2, когда мой вывод должен быть много дольше.

awk 'FNR==NR{a[$1]=$2 FS $3;next} $1 in a {print $0, a[$1]}' file2 file1 > output 

ответ

3

это работает, как ожидалось

$ awk 'NR==FNR{a[$1]=$2 FS $3; next} $1 in a{print $0, a[$1]}' file2 file1 

ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382 
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546 

нет предела, сколько file1 записей будет соответствовать в file2, но, очевидно, file2 ключи должны быть уникальными. Я не уверен, что вы получили, когда вы запускаете тот же скрипт.

Если вы не возражаете потерять заказ вы можете использовать join и sort ред файлы

$ join <(sort file1) <(sort file2) 

ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382 
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546 

с небольшим дополнительным жонглирования вы можете вернуть заказ (украшения/undecorate)

$ join -12 <(cat -n file1 | sort -k2) <(sort file2) | 
    sort -k2,2 | cut -d' ' -f2 --complement 

ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382 
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546 
+0

Ну, теперь мой ответ выглядит немного глупым;) –

+1

ну, это воскресенье ночью ... – karakfa

+0

Привет, спасибо, что вернулись. – dcp1234

1

Edit: видя вторую часть ответа karakfa, я понимаю, что весь Grep/вырезать цирк не требуется ... простое соединение имеет один и тот же результат. Это полезно, только если grepping уменьшает размер file1, так что grepping plus sorting дешевле, чем сортировка всего файла. join также может быть быстрее, если входные файлы меньше.


Если вы не ограничены в AWK, вы можете использовать Grep и основные утилиты (требуется Bash для подстановки процессов):

$ join <(grep -wFf <(cut -d ' ' -f 1 file2) file1 | sort) <(sort file2) 
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382 
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382 
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867 
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867 
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546 
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546 

От наизнанку:

  • cut -d ' ' -f 1 file2 извлекает первый столбец file2.
  • grep -wFf <(cut -d ' ' -f 1 file2) file1 | sort принимает извлеченный первый столбец из file2 и рассматривает его как файл аргумент Grep -f («Матч строки, которые соответствуют любой строке в этом файл»), и -F угощения линий как фиксированные строки вместо регулярных выражений. -w Уверен, что мы смотрим только на столбец в целом, подстроки не совпадают.

    Результат: sort, потому что join требует отсортированного ввода.

  • join затем берет результат всего этого, рассматривает его как первый файл и соединяется с <(sort file2).

Обратите внимание, что выход сортируется по алфавиту. Если он должен отображаться в том же порядке, что и в file, мы не можем использовать join.

+0

Это Ответ зависит от 'bash', который не был помечен в вопросе. Хотя это безопасная ставка, что bash существует в Linux-системе OP, и этот ответ обеспечивает жизнеспособное решение, вы должны указать, что это альтернативное решение *, чем тот, который запросил OP. – ghoti

+0

@ghoti Хороший момент, добавил. –

+0

Красиво сделано, спасибо. – ghoti