web-dev-qa-db-fra.com

bash comparant plusieurs colonnes dans deux fichiers de longueur différente

J'ai les données suivantes dans un fichier texte

data.txt

d1,40,gold
d2,30,silver
d3,20,bronze
d4,10,iron
d5,5,wood
d6,20,gold
d7,10,wood
d8,5,gold
d9,10,silver
 .
 .
 .

def.txt

gold,40
silver,30
bronze,20
iron,10
wood,5

ce dont j'ai besoin, c'est de comparer les données avec mon fichier de définition et d'ajouter le statut "ok" ou "nok" dans le fichier principal. Comme le fichier de données est très volumineux, je suis capable de comprendre avec la boucle while, mais cela prend beaucoup de temps. Y a-t-il un moyen optimisé?

data.txt

d1,40,gold,ok
d2,30,silver,ok
d3,20,bronze,ok
d4,10,iron,ok
d5,5,wood,ok
d6,20,gold,nok
d7,10,wood,nok
d8,5,gold,nok
d9,10,silver,nok
3
user261334

Grâce à la commande unique awk , je pense que ce serait plus rapide que d’utiliser une boucle while. Vous pouvez tester sa rapidité avec time commande devant la commande et voir si elle est rapide;)

awk -F, 'NR==FNR{ arr[$2]=$2 $1; next } 
    { print $0, (arr[$2]==$2 $3?"ok":"nok") }' OFS=, def.txt data.txt
d1,40,gold,ok
d2,30,silver,ok
d3,20,bronze,ok
d4,10,iron,ok
d5,5,wood,ok
d6,20,gold,nok
d7,10,wood,nok
d8,5,gold,nok
d9,10,silver,nok

Explication:

  • NR est défini sur 1 lorsque le premier enregistrement est lu par awk et incrémenté pour chaque enregistrement suivant lu dans un ou plusieurs fichiers d'entrée jusqu'à la fin de la lecture.

  • FNR est défini sur 1 lorsque le premier enregistrement est lu par awk et incrémenté pour chaque enregistrement suivant lu dans le fichier en cours et réinitialisé à 1 pour le prochain fichier d'entrée si plusieurs fichiers d'entrée.

  • alors NR == FNR est vrai pour le premier fichier seulement def.txt

  • arr[$2]=$2 $1; crée un tableau associatif nommé arr avec la clé sous la forme $2 et copie les deuxième et premier champs comme valeur.

  • Le jeton next permet d’exécuter le reste des commandes. Celles-ci ne seront exécutées que pour le ou les fichiers suivants, sauf le premier.

  • Ce print $0 imprime la ligne entière de data.txt et (arr[$2]==$2 $3?"ok":"nok") (connu sous le nom d’opérateur ternaire (condition?"if-true":"if-false") vérifie si la valeur de la clé dans arr[$2] était égal aux valeurs de $2 $3 (deuxième et troisième champs) dans data.txt puis affiche "ok" else "nok" .

  • Cela fonctionnera également si votre fichier data.txt et vos fichiers def.txt ne sont pas triés .

5
αғsнιη