2015-02-12 3 views
1

Я знаю, что были похожие вопросы, но у меня все еще есть немного проблем с получением вывода, который я хочу использовать awk FNR == NR ... У меня есть 2 файла такие, соединяющий 2 файла с соответствующими значениями столбцов с помощью awk

File 1: 
123|this|is|good 
456|this|is|better 
... 

File 2: 
aaa|123 
bbb|456 
... 

Так что я хочу присоединиться значения из файла 2/column2 в файл 1/column1 и выходной файл 1 (Col 2,3,4) и файл 2 (седловины 1).

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

ответ

3

С AWK вы могли бы сделать что-то вроде

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } $1 in val { $(NF + 1) = val[$1]; print }' file2 file1 

NF является количество полей в записи (строка по умолчанию), поэтому $NF последнее поле, и $(NF + 1) это поле после этого. Назначив сохраненное значение из прохода над file2, к нему будет добавлено новое поле перед его печатью.

Следует отметить: это ведет себя как внутреннее соединение, то есть печатаются только записи, ключ которых отображается в обоих файлах. Чтобы сделать это право присоединиться, вы можете использовать

awk -F \| 'BEGIN { OFS = FS } NR == FNR { val[$2] = $1; next } { $(NF + 1) = val[$1]; print }' file2 file1 

То есть, вы можете отказаться от условия $1 in val на действии конкатенирующего и-печати. Если $1 не находится в val, val[$1] пуст, и перед печатью будет добавлено пустое поле.

Но это, вероятно, лучше использовать join:

join -1 1 -2 2 -t \| file1 file2 

Если вы не хотите, ключевое поле, чтобы быть частью производства, трубы на выходе любой из этих команд через cut -d \| -f 2-, чтобы избавиться от него , т.е.

join -1 1 -2 2 -t \| file1 file2 | cut -d \| -f 2- 
+0

Вы можете избежать трубопровода, чтобы вырезать, добавить опцию Объединить : '-o 1.2.1.3,1.4,2.2' –

+0

Мне нравится использование' $ (NF + 1) '. Вы можете сделать это более awk-ish, перемещая выражение if вне фигурных скобок: '$ 1 в val {$ (NF + 1) = val [$ 1]; print} ' –

+0

@glennjackman О, это хороший момент. Однако я буду придерживаться 'cut', чтобы сбрить ключевое поле с выхода; опцион '-o' может решить проблему, как указано, и имеет свои преимущества, но я чувствую, что преимущество подхода' cut', которое он работает с произвольным количеством столбцов, перевешивает их здесь. Если бы производительность была заявлена ​​как проблема, все могло бы быть иначе. – Wintermute

1

Если файлы имеют одинаковое количество строк в том же порядке, то

paste -d '|' file1 file2 | cut -d '|' -f 2-5 
this|is|good|aaa 
this|is|better|bbb 

В комментарии к Wintermute я вижу, что файлы не отсортированы. С Баш, процесс замены удобны для сортировки на лету:

paste -d '|' <(sort -t '|' -k 1,1 file1) <(sort -t '|' -k 2,2 file2) | 
cut -d '|' -f 2-5 

Чтобы вновь заявить: это решение требует соответствие один-к-одному между файлами

+0

Полезно знать - всегда приятно иметь несколько подходов. – user3653270