classifique o arquivo B com base na coluna 3 do arquivo A sem alterar o conteúdo do arquivo A

classifique o arquivo B com base na coluna 3 do arquivo A sem alterar o conteúdo do arquivo A

Eu tenho o seguinte arquivo:

cat fileA.txt

seattle    1991  west
atlanta    1993  west
turlock    1998  west
marysville 2004  south
newyork    2007  north
canada     2004  west

E o segundo arquivo fica assim:

cat fileB.txt

popular
someWhatPopular
boring
popular
popular
popular

Gostaria de obter a seguinte saída fileB.txt:

popular popular popular someWhatPopular boring popular

Basicamente, estou tentando classificar fileB.txtpara fileA.txta terceira coluna

Eu tentei o seguinte código:

   #!/bin/bash
   sort -s -k3,3 fileA.txt fileB.txt

Mas não funcionou. Alguma sugestão? Estou bastante aberto a qualquer coisa que não exija codificação. Bash/awk/sed, etc.

Responder1

Este é um problema de estrutura de dados mais do que o do Linux. Você precisa de uma entrada comum (chave) em ambas as tabelas para vinculá-las, o mesmo que em qualquer 'banco de dados' e é uma boa prática manter uma chave única na primeira coluna de qualquer tabela de dados. Então você pode classificar e vincular o conteúdo de sua preferência.

Tomando algo como mapeamento @glennjackman , você define a chave de mapeamento como sendo norte, sul etc.

1 south somewhatPopular
2 west popular
3 north boring
4 east unexplored

em um arquivo chamado arquivo popularity. Alterar fileApara incluir uma chave exclusiva

1 seattle    1991  west
2 atlanta    1993  west
3 turlock    1998  west
4 marysville 2004  south
5 newyork    2007  north
6 canada     2004  west

então você pode manipular esses arquivos colocando- joinos na chave selecionada (no seu caso, a coluna 2 em popularitymapas para a coluna 4 em fileA), mas join precisa que ambos os arquivos sejam classificados no campo-chave, então

join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity) | sort -k2 | awk '{print $6}'

popular
popular
popular
somewhatPopular
boring
popular

Uma abordagem um pouco marreta, mas oferece mais flexibilidade.

Quebre o comando acima em cada tubo e você verá o que cada etapa faz.

Editar: Explicação dejoin -1 4 -2 2 # its in the man pages

Isso indica joinpara olhar a 4ª coluna da tabela 1 (-1 4) e encontrar valores correspondentes na 2ª coluna da tabela 2 (-2 2).

joinem seguida, compõe as colunas das duas tabelas em uma única tabela, mas inclui apenas a coluna-chave (norte, etc.) uma vez. Veja a saída de

join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity)

e deveria ser mais claro

Como tivemos que classificar as tabelas de dados para que joinfuncionassem, então

| sort -k2

a tabela combinada para colocá-los de volta em sua ordem original.

A coluna que você deseja é a coluna 6 na tabela combinada, então apenas

| awk '{print $6}'

para sair padrão.

Responder2

Você pode tentar pastejuntar os dois arquivos de "tabela", canalizar a saída para sorte cutreter apenas a quarta coluna.

A tentativa não testada (telefone celular agora) seria algo como

paste fileA fileB | sort -s -k3,3 | cut -f4

Responder3

Você pode obter o mapeamento alfabético com

paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)
north   boring
south   popular
west    someWhatPopular

E então um formulário com a saída desejada pode ser produzido com o awk:

awk '
    NR==FNR {map[$1] = $2; next} 
    {print map[$NF]}
' <(paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)) fileA.txt
someWhatPopular
someWhatPopular
someWhatPopular
popular
boring
someWhatPopular

informação relacionada