2012-05-23 1 views
1

Я новичок в Unix, и у меня возникли проблемы с присоединением двух текстовых файлов с разделителями табуляции на основе поля, имеющего дефисный индекс. Например:Присоединиться к столбцу с дефисным индексом в Unix

file1.txt 
33-47 10  22  -99  10 
33-48 15  22  165  456 
33-101 10  22  -99  15.8 
33-126 10  22  -99  15.5 
34-133 10  22  -99  13 
40-109 10  22  -99  12 
41-102 88  21  -99  20 
45-169 54  214  -99  4 
100-11 652  524  87  5 
101-25 45  54  153  8 
101-26 1285 12  155  9.5 

и

file2.txt 
1  5432 545  33-101 
1  5524 5420 33-126 
0  855520 52220 33-47 
0  5463 5420 34-133 
0  5563 5423 40-109 
1  6098 -99  40-109 

По существу, файл 1 является справочной таблицы, и я хочу, чтобы добавить соответствующую строку в файл 1 в файл 2, чтобы создать полную таблицу переменных, а именно:

file3.txt (expected) 
1  5432 545  33-101 10  22  -99  15.8 
1  5524 5420 33-126 10  22  -99  15.5 
0  855520 52220 33-47 10  22  -99  10 
0  5463 5420 34-133 10  22  -99  13 
0  5563 5423 40-109 10  22  -99  12 
1  6098 -99  40-109 10  22  -99  12 

Я использую Cygwin, и попытались первой сортировки полей в цифровой форме, как правило, и с LC_COLLATE = C локали, а также ряд AWK команд NR == РБН, но я все еще получаю blan k outfile.

Это все новое и очень расстраивающее. Пожалуйста, помоги, если можешь!

Спасибо!

ответ

1

Это работает для меня, но я не на Cygwin:

awk 'NR==FNR{info[$1]=gensub(/[^\t]*\t/,"",1)} NR!=FNR{printf"%s\t%s\n",$0,info[$NF]}' file1.txt file2.txt 

Я уверен, что кто-то может улучшить, что ...

+0

Это потрясающе и работает для меня. Я также обнаружил, что соединение работает, но некоторые из моих файлов имеют пробелы, бросающие все это. Если вы получите второй перевод, я был бы всегда благодарен! – akw

+0

Некоторые объяснения: – SignalToNoise

+0

Некоторые объяснения: Прочитать файл1 (NR == FNR) Построить информацию о массиве. Индексы - значения в 1-м столбце (awk использует строки как индексы) Значения информации о массиве [xx-yy] - строки = остальная часть строки gensub берет строку ($ 0) и заменяет первую строку, заканчивающуюся на tab/[^ \ t] * \ t/пустой строкой. Это удаляет первый col. Третий аргумент gensub означает замену только первого совпадения. /[^ \ t] * \ t /: регулярное выражение, соответствующее многим символам без табуляции, за которыми следует одна вкладка. Прочтите файл2 (NR!= FNR) $ NF: последнее слово в каждой строке. Случается, чтобы соответствовать индексам информации о массиве. print line ($ 0), добавить значение информации [$ NF] – SignalToNoise

1

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

Вот очень некрасиво способ:

a='{split($f, a, /-/); $f = sprintf("%05d%05d", a[1], a[2]); print}' 
join -1 4 -2 1 -o 1.1 1.2 1.3 0 2.2 2.3 2.4 2.5 2.6 2.7 2.8 \ 
    <(awk -v f=4 "$a" file2.txt | sort -k4,4) | 
    <(awk -v f=1 "$a" file1.txt | sort) \ 
    awk 'BEGIN {OFS = "\t"} {$4 = substr($4, 1, 5) + 0 "-" substr($4, 6, 5) + 0; print}' 

Выход:

0  855520 52220 33-47 10  22  -99  10 
1  5432 545  33-101 10  22  -99  15.8 
1  5524 5420 33-126 10  22  -99  15.5 
0  5463 5420 34-133 10  22  -99  13 
0  5563 5423 40-109 10  22  -99  12 
1  6098 -99  40-109 10  22  -99  12 

Если вы опустили -o выходной спецификации (и изменить поле от $4 до $1 в конечном awk), таким образом, укорачивая команду, это будет выглядеть так (первое поле сначала):

33-47 0  855520 52220 10  22  -99  10 
33-101 1  5432 545  10  22  -99  15.8 
33-126 1  5524 5420 10  22  -99  15.5 
34-133 0  5463 5420 10  22  -99  13 
40-109 0  5563 5423 10  22  -99  12 
40-109 1  6098 -99  10  22  -99  12 

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

У меня возникло искушение использовать sort -V (вариант версии) вместо использования прокладки. Он дает правильный порядок сортировки, но join не согласен.