Un script shell pour joindre deux fichiers


8

Je veux écrire un shell scriptqui obtiennent deux fichiers Aet B, et obtenir un résultat comme celui - ci:

Fichier A:

user_a tel_a addr_a
user_b tel_b addr_b

Fichier B:

process_1 user_a
process_2 user_a
process_3 user_b

Et le résultat:

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

Comment puis-je faire ceci? awkou autre chose?


2
Je pense que cela peut être fait en utilisant cutet pasteseulement, mais je ne comprends pas bien le synthax.
Bernhard

Mes fichiers ont de nombreux enregistrements et champs, je ne peux pas couper et coller !! Ce n'est qu'un échantillon.
Navid Farhadi

1
@NavidFarhadi pas copier-coller: il y a deux commandes réelles cutet pasteregardez leur page de manuel.
Matteo

Je peux charger complètement les deux fichiers en mémoire et je peux également utiliser awk.
Navid Farhadi

Je peux également utiliser Perl ou d'autres, s'ils étaient exécutables en ligne de commande Linux.
Navid Farhadi

Réponses:


15

join ...

join -1 2 -2 1 FileB FileA

Production

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

Les fichiers d'entrée doivent être triés par le champ clé ... Vos fichiers d'exemple sont déjà triés, donc ce n'était pas nécessaire, mais sinon vous pourriez incorporer le tri comme suit.

join -1 2 -2 1 <(sort -k2 FileB) <(sort FileA)

Que signifie les paramètres numériques?
Navid Farhadi

5
@Navid: Vous pouvez toujours obtenir la description la meilleure et la plus précise des paramètres d'une commande en vous référant au manuel , en tapant man joindans la ligne de commande du terminal ... -1 2   -2 1 signifie: joindre sur le '1er fichier 2e champ' et le ' 2nd-file 1st-field '
Peter.O

3

Depuis joinet pastene sont pas disponibles partout (ils ne sont pas sur mon système basé sur BusyBox, par exemple), voici comment le faire avec awk, comme demandé:

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

BTW vous avez manqué le séparateur A[$1]=$2 OFS $3... Voici une autre variante qui évite la boucle manuelle dans BEGIN, mais c'est à peu près la même chose (à awk ), bien qu'elle introduise un test de condition autrement inutile pour le deuxième fichier: awk 'NR==FNR {A[$1]=$2 OFS $3;next} {print $2, $1, A[$2]}' fileA fileB... (+ 1)
Peter.O
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.