Concatenando colunas horizontalmente. Imprimir apenas linhas que se cruzam na primeira coluna

3

Digamos que eu tenha dois comandos diferentes que geram conteúdo por colunas, por exemplo:

$ command_1

7049857 abc fdg hsi
5409858 xxx fyy hsi
540958  abc zzz hsi
54230956  rbc sss hsi

$ command_2

7049857 0 fdg free
5409858 0 fyy free
540958  2 zzz free

Eu gostaria de pegar silenciosamente colunas com índices x,y,z da saída de command_1 e as colunas com índices a,b,c da saída command_2 e imprimir uma nova saída: x,y,z,a,b,c .

Exemplo:

Emita a coluna de coluna 1 e 2 de commmand_2 : e a última coluna de command_1 :

$ new_command

7049857 0  hsi
5409858 0  hsi
540958  2  hsi

O que eu tenho até agora:

Sou relativamente novo em awk , mas sei que posso pegar as colunas correspondentes de cada um desses comandos com awk :

command_1 | awk '{print $x " " $y " " $z}'
command_2 | awk '{print $a " " $b " " $c}'

O acima concatena as colunas verticalmente, mas eu preciso concatená-las horizontalmente.

Imprimir somente as linhas que se cruzam na primeira coluna:

Digamos que é possível que command_2 tenha mais ou menos linhas que command_1 . No entanto, a primeira coluna de ambos os comandos contém itens pertencentes à mesma categoria (um ID de vários dígitos, como no exemplo acima)

Com isso, supondo que a primeira coluna de ambos os comandos seja classificada igualmente e que entradas novas ou ausentes só possam acontecer no final, como podemos garantir que apenas imprimamos as linhas para as quais temos entradas em command_1 e command_2 (ou seja, a interseção de ambos os comandos)? (o exemplo acima mostra isso)

    
por Amelio Vazquez-Reina 26.10.2011 / 18:46

2 respostas

6

Tente algo assim:

join <(command1) <(command2) | cut -d ' ' -f 1,5,4

O comando join recebe arquivos, não comandos, mas com um shell como o bash você pode usar a construção mostrada para transformar a saída do comando em um arquivo virtual.

Em vez de cut , você também pode usar awk , se você quiser.

Se você estiver fazendo muito isso, considere usar um mecanismo de banco de dados relacional.

    
por 26.10.2011 / 18:54
2

Se você quiser o awk, aqui vai uma ideia:

awk '
  NR==FNR {cmd1[$1] = $NF; next}
  $1 in cmd1 {print $1, $2, cmd1[$1]}
' <(command_1) <(command_2)

A variável FNR awk é o número da linha dentro do arquivo atual.
A variável NR é o número da linha de todas as linhas vistas até agora.
Assim, a condição NR==FNR só será verdadeira para o primeiro argumento de arquivo.

    
por 26.10.2011 / 20:22

Tags