#1 Le 10/02/2016, à 19:09
- manon123
[Résolu] Aide sur un Script de tri
Bonsoir,
J'ai suivi le cours sur OpenClassRoom : "Prenez le contrôle à l'aide de linux".
À 50 piges, j'essaie de comprendre le maximum de choses, mais c'est pas facile.
À la fin du cours un exercice est proposé :
Je vais vous demander de créer un script Bash qui fournit des statistiques sur l'utilisation des lettres dans une langue. Pour cela, vous allez devoir vous baser sur un fichier de dictionnaire contenant tous les mots de la langue française que vous pouvez télécharger ci-dessous :
exemple :
ABAISSA
ABAISSABLE
ABAISSABLES
ABAISSAI
ABAISSAIENT
[...] ==> Z
A partir de ce fichier (dico.txt) vous devez extraire le nombre de mots utilisant chaque lettre de l'alphabet de A à Z. Le script que vous allez créer (langstat.sh) prendra en paramètre le nom du fichier dictionnaire à analyser :
./langstat.sh dico.txt
Le résultat affiché dans la console devrait ressembler à ceci, de la lettre la plus utilisée à la moins utilisée:
278814 - E
229938 - A
219131 - I
210391 - R
207889 - S
179165 - N
176030 - T
158282 - O
[...] ==> Z
Cela signifie que la lettre E apparaît dans 278814 mots du dictionnaire, la lettre A dans 229938 mots, etc.
Voici ce que j'ai fait, en recherchant sur le web et en tâtonnant beaucoup :
#!/bin/bash
egrep [aA] dico.txt > lettre_a
A=`wc -l lettre_a | awk -F ' ' ' {print $1} ' `
echo "$A - A"
egrep [bB] dico.txt > lettre_b
B=`wc -l lettre_b | awk -F ' ' ' {print $1} ' `
echo "$B - B"
egrep [cC] dico.txt > lettre_c
C=`wc -l lettre_c | awk -F ' ' ' {print $1} ' `
echo "$C - C"
egrep [dD] dico.txt > lettre_d
D=`wc -l lettre_d | awk -F ' ' ' {print $1} ' `
echo "$D - D"
egrep [eE] dico.txt > lettre_e
E=`wc -l lettre_e | awk -F ' ' ' {print $1} ' `
echo "$E - E"
egrep [fF] dico.txt > lettre_f
F=`wc -l lettre_f | awk -F ' ' ' {print $1} ' `
echo "$F - F"
egrep [gG] dico.txt > lettre_g
G=`wc -l lettre_g | awk -F ' ' ' {print $1} ' `
echo "$G - G"
egrep [hH] dico.txt > lettre_h
H=`wc -l lettre_h | awk -F ' ' ' {print $1} ' `
echo "$H - H"
egrep [iI] dico.txt > lettre_i
I=`wc -l lettre_i | awk -F ' ' ' {print $1} ' `
echo "$I - I"
egrep [jJ] dico.txt > lettre_j
J=`wc -l lettre_j | awk -F ' ' ' {print $1} ' `
echo "$J - J"
egrep [kK] dico.txt > lettre_k
K=`wc -l lettre_k | awk -F ' ' ' {print $1} ' `
echo "$K - K"
egrep [lL] dico.txt > lettre_l
L=`wc -l lettre_l | awk -F ' ' ' {print $1} ' `
echo "$L - L"
egrep [mM] dico.txt > lettre_m
M=`wc -l lettre_m | awk -F ' ' ' {print $1} ' `
echo "$M - M"
egrep [nN] dico.txt > lettre_n
N=`wc -l lettre_n | awk -F ' ' ' {print $1} ' `
echo "$N - N"
egrep [oO] dico.txt > lettre_o
O=`wc -l lettre_o | awk -F ' ' ' {print $1} ' `
echo "$O - O"
egrep [pP] dico.txt > lettre_p
P=`wc -l lettre_p | awk -F ' ' ' {print $1} ' `
echo "$P - P"
egrep [qQ] dico.txt > lettre_q
Q=`wc -l lettre_q | awk -F ' ' ' {print $1} ' `
echo "$Q - Q"
egrep [rR] dico.txt > lettre_r
R=`wc -l lettre_r | awk -F ' ' ' {print $1} ' `
echo "$R - R"
egrep [sS] dico.txt > lettre_s
S=`wc -l lettre_s | awk -F ' ' ' {print $1} ' `
echo "$S - S"
egrep [tT] dico.txt > lettre_t
T=`wc -l lettre_t | awk -F ' ' ' {print $1} ' `
echo "$T - T"
egrep [uU] dico.txt > lettre_u
U=`wc -l lettre_u | awk -F ' ' ' {print $1} ' `
echo "$U - U"
egrep [vV] dico.txt > lettre_v
V=`wc -l lettre_v | awk -F ' ' ' {print $1} ' `
echo "$V - V"
egrep [wW] dico.txt > lettre_w
W=`wc -l lettre_w | awk -F ' ' ' {print $1} ' `
echo "$W - W"
egrep [xX] dico.txt > lettre_x
X=`wc -l lettre_x | awk -F ' ' ' {print $1} ' `
echo "$X - X"
egrep [yY] dico.txt > lettre_y
Y=`wc -l lettre_y | awk -F ' ' ' {print $1} ' `
echo "$Y - Y"
egrep [zZ] dico.txt > lettre_z
Z=`wc -l lettre_z | awk -F ' ' ' {print $1} ' `
echo "$Z - Z"
sort -f $*
Le fichier Dico : Téléchargement Dico
Je me doute qu'il y a plus facile.
Premier problème, lorsque je l'exécute, ça me crée un fichier pour chaque lettre, c'est normal?
Deuxième problème, je suis allé voir man sort et il dit d'employer l'option -f pour trier numériquement le fichier. Ici, j'ai repris toutes les variables avec * et bien sûr ça fonctionne pas.
Une explication serait la bienvenue. Je vois pas comment faire ça avec une fonction ou des conditions (attention, c'est mon premier script :-) ).
Je suppose qu'il me crée un fichier par lettre à cause de la direction :
> lettre_xxx
Merci beaucoup.
Dernière modification par manon123 (Le 10/02/2016, à 22:41)
Distro: Manjaro 20.1-2
Hors ligne
#2 Le 10/02/2016, à 20:12
- pingouinux
Re : [Résolu] Aide sur un Script de tri
Bonsoir,
Premier problème, lorsque je l'exécute, ça me crée un fichier pour chaque lettre, c'est normal?
Tel que tu l'as fait, oui.
Deuxième problème, je suis allé voir man sort et il dit d'employer l'option -f pour trier numériquement le fichier.
Pour trier numériquement, c'est sort -n (sort -f fait un tri sans tenir compte de la casse).
Je regarde ton script pour voir comment le simplifier.
Hors ligne
#3 Le 10/02/2016, à 20:27
- Watael
Re : [Résolu] Aide sur un Script de tri
la première simplification serait de factoriser les commandes dans une boucle itérant sur les lettres de l'alphabet.
Connected \o/
Welcome to sHell. · eval is evil.
En ligne
#4 Le 10/02/2016, à 20:31
- pingouinux
Re : [Résolu] Aide sur un Script de tri
Voilà !
Il y a une boucle sur les lettres. L'option -i de grep ignore la casse, et l'option -c donne le compte des lignes qui contiennent l'expression. Le tri s'effectue sur la sortie standard de la boucle.
#!/bin/bash
dico=$1
for lettre in {A..Z}
do
printf "%s - %s\n" $(grep -ic $lettre "$dico") $lettre
done | sort -rn
On doit pouvoir améliorer, car le fichier est ici lu entièrement pour chaque lettre.
Hors ligne
#5 Le 10/02/2016, à 20:52
- pingouinux
Re : [Résolu] Aide sur un Script de tri
#!/bin/bash
dico=$1
declare -A resul
while read mot
do
for lettre in {A..Z}
do
grep -q $lettre <<<"$mot" && ((resul[$lettre]++))
done
done <"$dico"
for lettre in "${!resul[@]}"
do
echo ${resul[$lettre]} "-" $lettre
done | sort -rn
Le dico n'est lu qu'une seule fois, ligne par ligne. En sortie, on n'a plus que la liste des lettres apparaissant au moins une fois.
Dernière modification par pingouinux (Le 10/02/2016, à 21:51)
Hors ligne
#6 Le 10/02/2016, à 21:32
- manon123
Re : [Résolu] Aide sur un Script de tri
Merci pingouinux,
Mais quand je lance le script n°2 après lui avoir donné le droit d'exécution, il ne se passe rien dans la console.
bruno@bruno-All-Series:~$ cd Bureau
bruno@bruno-All-Series:~/Bureau$ ./langstat2.sh dico.txt
Le curseur clignote et c'est tout.
Par contre le premier fonctionne.
Tu peux m'expliquer
"%s - %s\n" $(grep -ic $lettre "$dico") $lettre ?
Merci
Distro: Manjaro 20.1-2
Hors ligne
#7 Le 10/02/2016, à 22:02
- pingouinux
Re : [Résolu] Aide sur un Script de tri
Je pensais à tort que le script en #5 aurait été plus rapide que celui en #4, mais il prend un temps fou sur ton gros fichier dico.txt. Le tien, en #1, est le plus rapide, mais il n'est pas très joli…
printf "%s - %s\n" $(grep -ic $lettre "$dico") $lettre
C'est une impression avec format :
"%s - %s\n" : format, qui va être suivi de 2 chaînes de caractères (ici un nombre et une lettre)
$(grep -ic $lettre "$dico") : nombre d'occurrences de la lettre de lignes contenant la lettre dans le dico
$lettre : la lettre
On aurait pu faire :
echo $(grep -ic $lettre "$dico") "-" $lettre
Dernière modification par pingouinux (Le 16/03/2016, à 12:11)
Hors ligne
#8 Le 10/02/2016, à 22:42
- manon123
Re : [Résolu] Aide sur un Script de tri
Merci beaucoup pingouinux,
Je mets le sujet en résolu
Distro: Manjaro 20.1-2
Hors ligne
#9 Le 16/03/2016, à 05:51
- pingouinux
Re : [Résolu] Aide sur un Script de tri
Réponse au message personnel de mathieudex
Bonjour,
Il est préférable de poser ta question ici (ou dans une nouvelle discussion). Elle pourra ainsi profiter à la communauté, et tu multiplieras tes chances d'obtenir une réponse pertinente.
Ceci dit, je n'ai pas compris ce que tu voulais. Montre un exemple (petit fichier de départ et résultat souhaité).
Hors ligne
#10 Le 16/03/2016, à 10:36
- mathieudex
Re : [Résolu] Aide sur un Script de tri
Réponse au message personnel de mathieudex
Bonjour,
Il est préférable de poser ta question ici (ou dans une nouvelle discussion). Elle pourra ainsi profiter à la communauté, et tu multiplieras tes chances d'obtenir une réponse pertinente.Ceci dit, je n'ai pas compris ce que tu voulais. Montre un exemple (petit fichier de départ et résultat souhaité).
Bonjour,
J'ai créé une nouvelle discussion en expliquant un peu mieux ce que je souhaitais faire
Merci d'avance
Hors ligne