Je dois traiter une grande quantité de fichiers txt dans un dossier en utilisant le script bash. Chaque fichier contient des millions de lignes et ils sont formatés comme suit:
Fichier n ° 1:
en ample_1 200 it example_3 24 ar example_5 500 fr.b example_4 570 fr.c example_2 39 en.n bample_6 10
Fichier n ° 2:
de example_3 4 uk.n example_5 50 de.n example_4 70 uk example_2 9 en ample_1 79 en.n bample_6 1
…
Je dois filtrer par “en” ou “en.n”, trouver des occurrences en double dans la deuxième colonne, additionner la troisième colonne et obtenir un fichier sortingé comme ceci:
en ample_1 279 en.n bample_6 11
Voici mon script:
#! /bin/bash clear BASEPATH= FILES= TEMP_UNZIPPED="tmp" FINAL_RES="pg-1" #iterate each file in folder and apply grep INDEX=0 DATE=$(date "+DATE: %d/%m/%y - TIME: %H:%M:%S") echo "$DATE" > log for i in ${BASEPATH}${FILES} do FILENAME="${i%.*}" if [ $INDEX = 0 ]; then VAR=$(gunzip $i) #-e -> multiple condition; -w exact word; -r grep recursively; -h remove file path FILTER_EN=$(grep -e '^en.n\|^en ' $FILENAME > $FINAL_RES) INDEX=1 #remove file to free space rm $FILENAME else VAR=$(gunzip $i) FILTER_EN=$(grep -e '^en.n\|^en ' $FILENAME > $TEMP_UNZIPPED) cat $TEMP_UNZIPPED >> $FINAL_RES #AWK BLOCK #create array a indexed with page title and adding frequency parameter as value. #eg. a['ciao']=2 -> the second time I find "ciao", I sum previous value 2 with the new. This is why i use "+=" operator #for each element in array I print i=page_title and array content such as frequency PARSING=$(awk '{ page_title=$1" "$2; frequency=$3; array[page_title]+=frequency }END{ for (i in array){ print i,array[i] | "sort -k2,2" } }' $FINAL_RES) echo "$PARSING" > $FINAL_RES #END AWK BLOCK rm $FILENAME rm $TEMP_UNZIPPED fi done mv $FINAL_RES $BASEPATH/06/01/ DATE=$(date "+DATE: %d/%m/%y - TIME: %H:%M:%S") echo "$DATE" >> log
Tout fonctionne, mais cela prend beaucoup de temps à exécuter. Est-ce que quelqu’un sait comment obtenir le même résultat, avec moins de temps et moins de lignes de code?
Le shell UNIX est un environnement à partir duquel manipuler des fichiers et des processus et des appels de séquence vers des outils. L’outil UNIX que le shell appelle pour manipuler du texte est awk, donc utilisez-le:
$ awk '$1~/^en(\.n)?$/{tot[$1" "$2]+=$3} END{for (key in tot) print key, tot[key]}' file | sort en ample_1 279 en.n bample_6 11
Votre script a trop de questions à commenter, ce qui indique que vous êtes un débutant en programmation shell – obtenez les livres Bash Shell Scripting Recettes de Chris Johnson et Effective Awk Programming, 4ème édition, d’Arnold Robins.