объединить 2 строки на основе одинаковых значений столбца

У меня есть файл, как показано ниже.

47196436 47723284 name1 1.77273 42672249 52856963 name2 1.06061 52856963 430695 name2 1.16667 55094959 380983 name3 1.55613 17926380 55584836 name4 1.02461 3213456 34211 name4 1.11 54321 34211 name4 1.23 

Первые 2 столбца соответствуют основным ключам в моей таблице. Я пытаюсь объединить строки таким образом, что если есть одно и то же имя, все ключи будут в одной строке.

Я пытаюсь получить вывод как,

 47196436 47723284 name1 42672249 52856963 430695 name2 55094959 380983 name3 17926380 55584836 3213456 34211 54321 name4 

Я смог добиться этого частично, используя команду ниже.

 awk '{ x[$3]=x[$3] " " $2; } END { for (k in x) print k,x[k] >"OUTPUT1"; }' ccc.txt 

Однако это не дает мне результат правильно. Мне нужна помощь в дальнейшем изменении указанной команды.

4 Solutions collect form web for “объединить 2 строки на основе одинаковых значений столбца”

Решение perl :

 $ perl -ane '$h{$F[2]} .= " ".$F[0]." ".$F[1]; END { for $k (sort keys %h) { print $_," " for grep {!$seen{$_}++} split(" ",$h{$k}); print "$k\n"; } }' file 47196436 47723284 name1 42672249 52856963 430695 name2 55094959 380983 name3 17926380 55584836 3213456 34211 54321 name4 

Ужасно, но, похоже, делает работу

 awk '$3 != prev {if (NR != 1) print prev; prev=$3; delete a}; !($1 in a){a[$1]++; printf "%s ", $1}; !($2 in a){a[$2]++; printf "%s ", $2}; END {print prev}' ccc.txt 47196436 47723284 name1 42672249 52856963 430695 name2 55094959 380983 name3 17926380 55584836 3213456 34211 54321 name4 

Вот еще один подход Perl:

 $ perl -ane 'foreach(@F[0..1]){$k{$F[2]}{$_}++} END{ foreach $v (sort keys(%k)){ print "$_ " foreach(keys(%{$k{$v}})); print "$v\n" }; } ' file 

Это дает:

 47723284 47196436 name1 42672249 430695 52856963 name2 380983 55094959 name3 34211 55584836 17926380 54321 3213456 name4 

объяснение

ОК, я признаю, вышеприведенный скрипт Perl не является примером простого для понимания Perl. Я использую много трюков, и они запутывают код. Я представляю здесь одно и то же решение, но отформатированное как скрипт и использую более подробный подход:

 #!/usr/bin/perl ## This is the hash that will store our values. my %k; ## Read through the input file line by line ## saving each line as $line. This is what the -n ## switch to perl means, only there each line is saved ## in the special variable $_. while (my $line=<>) { ## Split the line into the @F array. This is ## what the -a switch does. #chomp($line); my @F=split(/\s+/,$line); ## Populate the %k hash that we defined at the beginning. ## This is a hash of hashes, it looks like this: ## $hash{key1}{key2}=value ## In this case, we are saying: ## $hash{3rd field}{1st field}=1 ## $hash{3rd field}{2nd field}=1 ## This just serves to add the 1st and 2nd fields ## to the list of fields for this $F[2] (the 3rd field, the name). ## A side effect of this is that hash keys are unique so duplicates ## are automatically removed. $k{$F[2]}{$F[0]}=1; $k{$F[2]}{$F[1]}=1; } ## We have now finished processing the file ## (this is the END{} block above), so let's print. ## This saves the keys of the hash %k in the @names array ## sorted alphabetically. my @names=(sort keys(%k)); ## Go through each of the names, saving ## them as $name foreach my $name (@names) { ## Now, iterate through the values associated ## with the current $name. These are saved as the ## keys of the hash %k{$name} foreach my $value ( (keys(%{$k{$name}})) ){ print "$value "; } ## Now print the name as well print "$name\n"; } 

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

Если вы не возражаете против использования gawk >= 4.0 , это (что почти так же, как у terdon ) приведет к желаемому результату, с дополнительным именем и порядком клавиш:

 NF { Names[$3][$1] = 1; Names[$3][$2] = 1; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; # if you want `Name` ordered for (Name in Names) { PROCINFO["sorted_in"] = "@ind_num_asc"; # if you want `Key` ordered for (Key in Names[Name]) { printf("%s ", Key); } print Name; } } 

дает:

 47196436 47723284 name1 430695 42672249 52856963 name2 380983 55094959 name3 34211 54321 3213456 17926380 55584836 name4 
  • объединить несколько строк данных, имеющих одно общее поле
  • Нейтрализация данных из Windows в Unix
  • Какие сайты можно добавить в тост?
  • Уведомление IRSSI - методом вытягивания
  • Как заменить все точки с запятой после первого?
  • Скрипт для удаления определенных элементов span из файла HTML
  • Сообщение «Не найдено» при запуске 32-битного двоичного файла в 64-битной системе
  • Проблема зависимости Perl
  • Использование kornshell или Perl для обхода разрешений, необходимых для root
  • Как разбить файл на несколько файлов на основе шаблона с помощью perl?
  • Sed / awk / perl: порядок реверсирования значений, разделенных запятыми, сохранение другого текста
  • Interesting Posts

    Как И-слова в поиске zypper?

    Почему я получаю «Нет виртуальной папки, прерывая», когда пытаюсь помечать сообщения в Mutt?

    Как заменить только N-е вхождение шаблона в файл?

    cp -attributes-only документирован, но не работает «сейчас»?

    Дата последнего изменения в Unix

    Найдите самую длинную соответствующую часть с двумя бинарными файлами

    Закрытая сеть DHCP + DNS – обновление сборочной стороны in-addr.arpa, передняя сторона отказывается обновлять

    Как обеспечить, чтобы строка, интерполированная в подстановку sed, избегала всех метамарков

    как предупреждать о пользовательских квотах пользователя ftp в оболочке / sbin / nologin?

    Как добавить «Сделать исполняемый файл» и «Запустить» в контекстное меню «Элементарный файловый менеджер ОС»?

    Соединение VNC занимает много времени, чтобы подключиться (по существу … никогда)

    Как решить проблему dracut, когда intall Fedora 21

    Перемещение последних файлов из одного каталога в другой

    MacBook Air (середина 2013 года) не может приостановиться должным образом после отсоединения от сети переменного тока

    как я могу установить приглашение для входа как можно скорее в последовательности загрузки?

    Linux и Unix - лучшая ОС в мире.