Bash: Tendo 2 arquivos, como eu verifico se um certo nome no primeiro também aparece no segundo

1

Ok, o problema é um pouco mais complexo do que isso

Eu tenho 2 arquivos, digamos arquivo1 e arquivo2 , cada um com os seguintes dados:

name of the game, hours spent playing it, last 7 days

arquivo1:

game1 100 20
game3 40   5

arquivo2:

game1 90  25
game4 40   2

Objetivos:

  • se um jogo estiver em ambos os arquivos, subtraia as horas gastas jogando de file1 - file2

  • Se um jogo estiver apenas em arquivo1 , mostre-o, mas como o original (arquivo1 - 0)

  • Se um jogo estiver apenas em arquivo2 , mostre-o, mas como o negativo do original (0 - arquivo2)

Como posso fazer isso em bash ?

    
por Fosh 19.11.2016 / 02:42

2 respostas

0

Resposta pronta para uso, presumindo que os arquivos estejam classificados:

awk '{$2= -$2; $3= -$3} 1' file2 |
  join -a1 -a2 file1 - |
  awk 'NF > 3 {$2+=$4; $3+=$5; NF=3} 1'

Saída na entrada fornecida:

game1 10 -5
game3 40 5
game4 -40 -2

(Se os arquivos não estiverem classificados, apenas os classifique e mantenha-os classificados. Isso facilitará as coisas.)

Observe que isso usa apenas os recursos POSIX de join e Os recursos POSIX do Awk , por isso vai funcionar em praticamente qualquer lugar.

$2 no Awk é uma referência ao segundo campo. $3 é uma referência ao terceiro campo (de cada linha do arquivo processado). 1 aparecendo fora das chaves {...} significa apenas "true", então a ação padrão de imprimir a linha é executada.

Essencialmente, o primeiro comando Awk apenas transforma os números em file2 em números negativos.

O comando join une file1 ao texto fornecido em sua entrada padrão (o que recebe do Awk). O - após file1 no comando join (em vez de outro nome de arquivo) significa "usar entrada padrão". As opções -a1 e -a2 significam que qualquer linha não parável no primeiro ou no segundo arquivo é enviada como está.

O comando Awk final pega as linhas que foram emparelhadas, isto é, linhas nas quais o N umber de F ields é maior que 3 ( NF > 3 ) e adiciona seu quarto campo para o segundo campo, adiciona seu quinto campo ao terceiro campo e, em seguida, trunca os quarto e quinto campos.

Mais uma vez, as% externas% chaves de1 finais são usadas para acionar a ação padrão do Awk, "imprimir".

(Veja este tutorial para mais e aprenda o Awk corretamente.)

Há muita coisa acontecendo aqui. Eu recomendo executar cada parte desses comandos antes de adicionar a próxima parte. Primeiro:

awk '{$2= -$2; $3= -$3} 1' file2

e estudar e entender isso. Então:

awk '{$2= -$2; $3= -$3} 1' file2 |
  join -a1 -a2 file1 -

E estude e entenda isso. (Também tente deixar de fora os -a1 e -a2 sinalizadores, ou deixando de fora apenas um deles.)

Em seguida, use o comando completo:

awk '{$2= -$2; $3= -$3} 1' file2 |
  join -a1 -a2 file1 - |
  awk 'NF > 3 {$2+=$4; $3+=$5; NF=3} 1'

E veja se faz mais sentido.

    
por 19.11.2016 / 02:52
0

Deselegante bash , join e GNU sed variante:

join -a1 -a2 -o 0 1.2,2.2,1.3,2.3 file1 <(sed 's/ \([0-9]*\)/ -/g' file2) | \
sed 's/ -/-/g;s/[0-9]*-[0-9]*/$((&))/g;s/.*/echo &/eg'

Saída:

game1 10 -5
game3 40 5
game4 -40 -2
    
por 19.11.2016 / 06:50