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.txt
para fileA.txt
a 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 fileA
para 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- join
os na chave selecionada (no seu caso, a coluna 2 em popularity
mapas 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 join
para olhar a 4ª coluna da tabela 1 (-1 4) e encontrar valores correspondentes na 2ª coluna da tabela 2 (-2 2).
join
em 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 join
funcionassem, 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 paste
juntar os dois arquivos de "tabela", canalizar a saída para sort
e cut
reter 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