#1 Le 25/07/2007, à 14:03
- Foulweather
[Résolu] Script bash pour un débutant
Bonjour.
Je cherche à apprendre l'écriture de scripts bash, notamment à partir du livre de Christophe Blaess (Eyrolles) et de ressources trouvées sur Internet. Mes débuts sont laborieux et peu fructueux. Peut-être ai-je été trop ambitieux pour démarrer. Aussi un coup de main serait le bienvenu. J'ai cherché à écrire un script qui extraie une donnée figurant entre parenthèses d'une liste d'enregistrements quelconques, en l'occurrence les signataires d'une pétition récupérée sur internet.
Chacun de ces enregistrements est constitué selon le modèle "* Prénom NOM (profession),". Il m'a semblé qu'il était nécessaire de déclarer une variable correspondant à un enregistrement puis d'extraire la chaîne qui m'intéresse, celle concernant la profession, en utilisant la présence des parenthèses.
Ma première question serait donc : est-il possible de définir une variable en n'utilisant que des expressions rationnelles ? Par exemple quelque chose comme : enregistement=${^\**$,}, autrement dit chaîne=commence par *, longueur quelconque, finit par une virgule. Ne riez pas : comme ça ne marche pas je me doute bien que c'est nul. Sinon comment procéder ?
Deuxième question : comment à partir de la liste obtenue, éliminer ensuite les redondances et classer les professions selon leur fréquence ?
Merci pour votre aide éventuelle.
Dernière modification par Foulweather (Le 26/07/2007, à 08:34)
Hors ligne
#2 Le 25/07/2007, à 14:42
- Black_pignouf
Re : [Résolu] Script bash pour un débutant
Salut!
Je n'ai pas de Linux-like sous la main, je ne peux donc pas trop t'orienter...
Mais l'expression rationelle correspondante à "Prénom NOM (profession)" ressemble à (varie selon que tu l'utilises sous bash, vim, Ruby ou autre):
^\*\s+(.+?)\s+(.+)\s+\((.+)\)$
^ $ se doivent d'être aux extremités de ton expression.
\* pour une étoile
\s+ pour un espace ou +
(.+?) pour une chaine quelconque = prénom
\s+ pour un espace ou +
(.+?) pour une chaine quelconque = nom
\s+ pour un espace ou +
\( parenthèse ouvrante
(.+) = profession
\) fin de la parenthèse
Les .+ sont entre parenthèses pour les enregistrer en mémoire, et les réutiliser à coup de $1 $2 $3 (je crois)
Sinon, je ne saurais trop te conseiller Ruby, très à l'aise sur les manipulations de chaînes de caractères et de tableaux. Pratique pour travailler sur les fréquences ou éliminer les redondances!
Bon courage,
Eric
Hors ligne
#3 Le 25/07/2007, à 16:55
- Black_pignouf
Re : [Résolu] Script bash pour un débutant
SInon, pour éditer tes regexp, je te conseille vivement kregexpeditor.
Hors ligne
#4 Le 25/07/2007, à 18:32
- Foulweather
Re : [Résolu] Script bash pour un débutant
Je vais essayer d'aller un peu plus loin en expérimentant ces expressions. Mais juste une précision : il n'est pas complètement stupide de chercher à définir une variable avec des expressions rationnelles ? Je demande de l'indulgence pour ma "naïveté", je ne suis qu'un très modeste débutant autodidacte, et littéraire de formation.
Hors ligne
#5 Le 25/07/2007, à 18:42
- BlaireauOne
Re : [Résolu] Script bash pour un débutant
L'idéal serait de nous communiquer :
- un petit échantillon du fichier à traiter
- ce que tu souhaites en sortie du traitement de ce fichier
ce sera une bonne base à partir de laquelle on pourra t'aider
Hors ligne
#6 Le 25/07/2007, à 20:00
- Foulweather
Re : [Résolu] Script bash pour un débutant
Voici un échantillon (avec les noms de famille modifiés) :
* Didier WXXXX (Réalisateur),
* Sandra QXXXX (Enseignante, 93),
Ce que je souhaiterais en sortie c'est le contenu de ce qui est entre parenthèses :
Réalisateur
Enseignante, 93
(Au passage un détail qui me surprend c'est que le fichier des données à traiter, affiché dans un shell avec la commande "cat" signale chaque nouvel enregistrement sur une nouvelle ligne avec en tête de ligne *, alors qu'édité avec Gedit c'est #. Je précise que le fichier a été récupéré à partir d'un copié-collé d'une page web.)
On voit qu'il y a des données parasites dans le "champ profession" qu'idéalement il faudrait pouvoir supprimer. Enfin, dans une étape ultérieure plutôt que d'avoir "Enseignante" répétée, par exemple, 50 fois, il serait, je pense, intéressant d'avoir le nombre d'occurrences pour chacune des professions.
Cela dit, je ne voudrais surtout pas abuser de la compétence ou du temps de qui que ce soit. Ce n'est pour moi qu'un exercice d'entraînement, que j'ai d'ailleurs un peu honte de ne pas savoir mener à bien seul, sans ignorer non plus que je grille les étapes et que je devrais m'appliquer à des exercices plus appropriés à mon niveau.
Hors ligne
#7 Le 25/07/2007, à 20:50
- BlaireauOne
Re : [Résolu] Script bash pour un débutant
Voici un échantillon (avec les noms de famille modifiés) :
* Didier WXXXX (Réalisateur),
* Sandra QXXXX (Enseignante, 93),Ce que je souhaiterais en sortie c'est le contenu de ce qui est entre parenthèses :
Réalisateur
Enseignante, 93
Exemple de fichier en entrée :
* Didier WXXXX (Réalisateur),
* Sandra QXXXX (Enseignante, 93),
# Dolly AAAAA (infirmiere),
# Eric ABBBB (policier,75),
* Lio AZZZZ (infirmiere,75),
* Lea ERRRR (infirmiere,92),
* Didier QEEEE (Enseignant ),
* Loic TREEE (Enseignant),
Script utilisant awk :
Liens utiles sur :
- awk : http://www.shellunix.com/awk.html
- les regexp : http://www.shellunix.com/regexp.html
#
### 1._ Découpage avec les caractères séparateurs parenthèses
### résultat : profession = champ n° 2
### 2._ Tri du fichier des professions.
#
awk -F"[()]" ' { print $2 } ' liste.txt | sort > tmp1
#
### Décompte par profession sans tenir compte du département
#
awk -F"," '
{
gsub(/ /,"",$1)
if (NR == 1) {
Precedent=$1
}
if ($1 == Precedent) {
incr++
} else {
print "- "Precedent" : "incr
Precedent=$1
incr=1
}
}
END {
print "- "Precedent" : "incr
} ' tmp1 > statistiques.txt
cat statistiques.txt
rm tmp1
Résultat dans fichier statistiques.txt :
- Enseignant : 2
- Enseignante : 1
- Réalisateur : 1
- infirmiere : 3
- policier : 1
Hors ligne
#8 Le 25/07/2007, à 21:47
- Black_pignouf
Re : [Résolu] Script bash pour un débutant
Joli!
En Ruby, ca donne ca:
toutes_les_lignes=File.readlines("liste.txt")
sans_doublons=toutes_les_lignes.uniq
professions=Hash.new
sans_doublons.grep(/^\*.+\s+.+\s+\((.+?),?\s*\d*\),?$/){
nom_de_la_profession=$1
professions[nom_de_la_profession]||=0
professions[nom_de_la_profession]+=1
}
professions_triees_par_occurence=professions.sort_by{|nom,occurence| occurence}.reverse
professions_triees_par_occurence.each{|nom,occurence|
puts nom+" : "+occurence.to_s
}
ce qui renvoie:
infirmiere : 2
Enseignant : 2
Enseignante : 1
Réalisateur : 1
(les lignes doivent commencer par * pour être lue)
Hors ligne
#9 Le 26/07/2007, à 07:49
- Foulweather
Re : [Résolu] Script bash pour un débutant
C'est exactement le résultat que je cherchais à obtenir. Je suis franchement impressionné. Ma demande était élémentaire, la réponse pour l'obtenir l'est beaucoup moins. Personnellement, je me dis qu'il me faudra plusieurs années d'efforts pour parvenir à ce genre de résultats.
Ce que j'aurais tendance à retenir aussi c'est que Bash, Sed, Awk... Ruby et les autres sont plus ou moins concurrents ou complémentaires et qu'il faut savoir choisir le mieux adapté.
BlaireauOne et Black_pignouf merci.
Hors ligne
#10 Le 26/07/2007, à 09:56
- BlaireauOne
Re : [Résolu] Script bash pour un débutant
Ce que j'aurais tendance à retenir aussi c'est que Bash, Sed, Awk... Ruby et les autres sont plus ou moins concurrents ou complémentaires et qu'il faut savoir choisir le mieux adapté.
BlaireauOne et Black_pignouf merci.
L'intérêt de sed et awk est d'être en standard sur toutes les machines UNIX ou LINUX.
Ruby, Python, Perl... sont beaucoup plus puissants mais pas installés en standard à ma connaissance.
Hors ligne