Um script de shell para juntar dois arquivos

8

Eu quero escrever um shell scriptque tem dois arquivos Ae Be obter um resultado como este:

Arquivo A:

user_a tel_a addr_a
user_b tel_b addr_b

Arquivo B:

process_1 user_a
process_2 user_a
process_3 user_b

E o resultado:

user_a process_1 tel_a addr_a
user_a process_2 tel_a addr_a
user_b process_3 tel_b addr_b

Como posso fazer isso? awkou alguma outra coisa?

Navid Farhadi
fonte
2
Eu acho que isso pode ser feito usando cute pastesomente, mas eu não entendo a sintaxe correta.
Bernhard
Meus arquivos têm muitos registros e campos, não consigo recortar e colar !! Esta é apenas uma amostra.
Navid Farhadi
1
@ NavidFarhadi não recortar e colar: existem dois comandos reais cute pasteconsulte a página de manual.
Matteo
Eu posso carregar os dois arquivos completamente na memória e também posso usar o awk.
Navid Farhadi
Eu também posso usar perl ou outros, se eles foram executáveis ​​na linha de comando do linux.
Navid Farhadi

Respostas:

15

join ...

join -1 2 -2 1 FileB FileA

Resultado

user_a process_1 tel_a addr_a
user_a process_2 tel_a addr_a
user_b process_3 tel_b addr_b

Os arquivos de entrada precisam ser classificados pelo campo-chave ... Seus arquivos de exemplo já estão classificados, portanto, não havia necessidade; caso contrário, você poderia incorporar a classificação da seguinte forma.

join -1 2 -2 1 <(sort -k2 FileB) <(sort FileA)
Peter.O
fonte
O que significa os parâmetros numéricos?
Navid Farhadi
5
@Navid: Você sempre pode obter a descrição melhor e mais precisa dos parâmetros de um comando consultando o manual , digitando man joinna linha de comando do terminal ... -1 2   -2 1 significa: ingressar no '1º arquivo 2º campo' e no ' Segundo arquivo 1st-field '
Peter.O
3

Como joine pastenão está disponível em todos os lugares (eles não estão no meu sistema baseado no BusyBox, por exemplo), veja como fazê-lo com o awk, conforme solicitado:

awk 'BEGIN {
    while( (getline < "fileA") > 0) A[$1]=$2 OFS $3 # read fileA into the array A
    close("fileA")
  } {
    print $2, $1, A[$2]
  }' fileB
dubiousjim
fonte
BTW, você perdeu o separador A[$1]=$2 OFS $3... Aqui está outra variante que evita o loop manual em BEGIN, mas é praticamente o mesmo (para awk ), embora introduza um teste de condição desnecessário para o segundo arquivo: awk 'NR==FNR {A[$1]=$2 OFS $3;next} {print $2, $1, A[$2]}' fileA fileB... (+ 1)
Peter.O