2013-09-20 2 views
2

кот Error00Как Grep два столбца из одного файла

4 0 375 
4 2001 21 
4 2002 20 

кошка Error01

4 0  465 
4 2001 12 
4 2002 40 
4 2016 1 

Я хочу, чтобы результат, как показано ниже

4 0  375 465 
4 2001 21 12 
4 2002 20 20 
4 2016 -  1 

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

keylist=$(awk '{print $1,$2'} Error0[0-1] | sort | uniq) 
for key in ${keylist} ; do 
echo ${key} 
     val_a=$(grep "^${key}" Error00 | awk '{print $3}') ;val_a=${val_a:---} 
     val_b=$(grep "^${key}" Error01 | awk '{print $1,$2}') ; val_b=${val_b:--- --} 
     echo $key ${val_a} >>testreport 
done 

я м адресности в oputput ниже

4  375 465 
0 
4  21 12 
2001 
4  20 20 
2002 
4  -  1 
2016 
+0

Есть несколько вопросов на этом сайте о том, как объединить два файла в Awk. Вы не объясняете, как получить желаемый результат (как представляется, нетривиальное переупорядочение полей ввода), поэтому трудно обеспечить фактический рабочий код. Пожалуйста, уточните это или получите что-то вроде 'awk '{k = $ 1": "$ 2} NR == FNR {a [k] = $ 3; b [k] = $ 4; ...следующий; } {печатать $ 1, $ 2, b [k], $ 7, a [k], ...} ''из более ранних вопросов. – tripleee

ответ

1

grep не является действительно правильным инструментом для этой работы. Вы можете играть с awk или Perl (или Python, или ...), или вы можете использовать join. Тем не менее, join подключается только к одному столбцу за раз, и вам кажется, что нужно подключиться к двум столбцам. Итак, нам придется массировать данные, чтобы они работали с join. Я собираюсь предположить, что вы используете bash, и у них есть process substitution. Вы можете выполнять эту работу без нее, но она запутана и включает временные файлы (и ловушки для их очистки и т. Д.).

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

$ join -o 0,1.2,2.2 -a 1 -a 2 -e '-' \ 
>  <(sed 's/ */:/' Error00 | sort) \ 
>  <(sed 's/ */:/' Error01 | sort) | 
> sed 's/:/ /' 
4 0 375 465 
4 2001 21 12 
4 2002 20 40 
4 2016 - 1 
$ 

's/ */:/' операция заменяет первую последовательность из одного или нескольких заготовок с двоеточием; входные данные имеют две заготовки между 4 и 0 в первой строке Error00. Вход в join должен быть в отсортированном порядке поля соединения, здесь первое поле. Результатом является поле объединения, второй столбец Error00 и второй столбец Error01 (помня, что второй столбец после первых двух был сплавлен двоеточием). Если в первом файле есть непревзойденная строка, создайте выходную строку (-a 1); то же самое для второго файла; и для недостающих полей вставьте тире (-e '-'). Финал sed удаляет двоеточие, которое было добавлено.

Если вы хотите, чтобы данные форматировались, пропустите его через awk.

$ join -o 0,1.2,2.2 -a 1 -a 2 -e '-' \ 
>  <(sed 's/ */:/' Error00 | sort) \ 
>  <(sed 's/ */:/' Error01 | sort) | 
> sed 's/:/ /' | 
> awk '{printf("%s %-6s %-6s %s\n", $1, $2, $3, $4)}' 
4 0  375 465 
4 2001 21  12 
4 2002 20  40 
4 2016 -  1 
$ 
+0

Hi Jonathan Это очень полезно, спасибо большое. На самом деле я сделал ошибку при публикации этой темы. У меня 15 файлов, а не 2 Error00 до Error15, там я не могу использовать Join. Поэтому у меня есть awk здесь. можете ли вы предложить для этого. –

+0

У меня есть решение, используя команду tr newkey = 'echo $ key | tr "|" "" echo $ {newkey} $ {val_a} "" $ {val_b} "" $ {val_c} >> testreport –

+0

В [Очистить внешнее объединение трех файлов, сохраняющих членство в файлах] есть расширение для трех файлов: //stackoverflow.com/questions/17507765/bash-clean-outer-join-of-three-files-preserving-file-membership). Есть обобщение на N файлов в [Что такое самый простой способ присоединиться к столбцам из переменного количества файлов?] (Http://stackoverflow.com/questions/18466662/what-is-the-simplest-method-to-join -columns-from-variable-number-of-files-using) Для каждого есть ответы на 'awk'. Но, пожалуйста, не забудьте задать реальный вопрос - мы можем ответить только на то, что вы просите. –

4

Один awk один лайнер может справиться с этим легко:

awk 'FNR==NR{a[$1,$2]=$3;next}{print $1,$2,(a[$1,$2]?a[$1,$2]:"-"),$3}' err0 err1 
4 0 375 465 
4 2001 21 12 
4 2002 20 40 
4 2016 - 1 

Для форматного вывода вы можете использовать printf вместо print.Как Jonathan Leffler предложить:

printf "%s %-6s %-6s %s\n",$1,$2,(a[$1,$2]?a[$1,$2]:"-"),$3 
4 0  375 465 
4 2001 21  12 
4 2002 20  40 
4 2016 -  1 

Однако общее решение заключается в использовании column -t для хорошего выхода таблицы:

awk '{....}' err0 err1 | column -t 
4 0  375 465 
4 2001 21 12 
4 2002 20 40 
4 2016 - 1 
+0

Имейте в виду, что 'column' не является командой POSIX, поэтому он недоступен везде (платформы Solaris, HP-UX, AIX, вероятно, недоступны). Это не должно вызывать это решение, которое достаточно хорошо работает для двух файлов (но обратите внимание, что есть проблема, если порядок двух файлов отменен - ​​или оба файла имеют записи, которые не находятся в другом). –

Смежные вопросы