Bonjour
Je cherche des idées pour améliorer (rapidité d'exécution) mon script bash . Il permet de traiter de gros fichiers. Avez vous des idées?
Le code
Merci
Tio
Bonjour
Je cherche des idées pour améliorer (rapidité d'exécution) mon script bash . Il permet de traiter de gros fichiers. Avez vous des idées?
Le code
Merci
Tio
Bonjour Tio,
Tu peux ne pas utiliser :Envoyé par Tiolebucheron
echo devant les variables du style ${line:n:m}
echo $var | sed, mais sed <<<"$var" (qui ne sont d'ailleurs pas indispensables, des remplacements de paramètres successifs de la même variable
une seule instance de sed : sed 's/anc/nouv/; s/anc2/nouv2/'
awk | sed : c'est soit awk soit sed, mais pas les deux
bc pour calculer des entiers
::
bref, limiter au strict minimum l'utilisation de programmes externes.
-
les tests depuis $l1 jusqu'à $ville, peuvent réaliser dans une boucle for. Ça ne fera pas ganer de temps mais de l'espace...
-
une petite question : à quoi servent tous ces guillemets ?
Oui en effet il y a matière a améliorer. Mes cours de shel remonte à 10 ans maintenant, un peu rouillé le gars.
Pour les guillemets une fois qu'une commande fonctionne j'ai reporté la même chose partout. par contre j'ai par trop compris l'histoire du for!!!
Je serai a mon bureau dans une heure je fais dejà les premières modifications et reposte le nouveau code.
MErci pour l'aide
tio
Le test [ -z "$ville" ] || [ "$ville" = "" ] fait 2 appels. Il vaut mieux le remplacer par un connecteur OR interne => [ -z "$ville" -o "$ville" = "" ]
Toutetois c'est inutile vu que l'option -z teste variable vide donc l'égalité avec rien est implicite => [ -z "$ville" ] est bien suffisant
Effectivement tous ces guillemets sont inutiles => ville="'$ville'" marche parfaitement
Moi on plus. Peut-être un for x in `cat fichier` mais personnellement j'apprécie pas trop cette syntaxe car si le fichier contient des espaces dans ses mots, le for traitera chaque mot avec comme 2 éléments séparés. Je préfère de loin la syntaxe cat fichier |while read x
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Re,
Je rencontre des difficultés pour enlever l'echo de cet commande
majic3=$(echo "${line:18:6}" | sed -e 's/[[:blank:]]*$//')
Pouvez-vous m'aider?
Merci
PS : 2 seconde de gagner déjà (sur un test de 80 lignes traitées)
Si la variable ne contient pas d'espaces, peut-être
Code : Sélectionner tout - Visualiser dans une fenêtre à part majic3=${line:18:6}; majic3=${majic3%% *}
Oui Merci pour vos réponse mais les espaces à supprimer sont à la fin de la chaine de caractère, ce n'est pas l'ensemble des espaces.
Un autre exemple
Merci de votre aide
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 nom=$(echo "${line:56:60}" | awk 'BEGIN{FS="/"} {print $1}' | sed -e "s/'/''/g") prenom=$(echo "${line:56:60}" | awk 'BEGIN{FS="/"} {print $2}') prenom=$(echo "$prenom" | sed -e 's/[[:blank:]]*$//' | sed -e "s/'/''/g")
Peut être remplacé par
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 cpt=$(echo "($cpt + $un)" | bc) if [ "$(echo "($cpt % $cent)" | bc)" = 0 ] then END=$(date +%s) tps_execution fi
Apparemment, le script fait beaucoup de mise en forme ; je pense que la comande printf pourrait faire une bonne part du boulot.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 ((cpt+=$un)) ((cpt%$cent)) || { END=$(date +%s); tps_execution; }
Merci on est descendu en dessous des 4 secondes. contre 8 au départ.
Le code
Je vous met une nouvelle version
Je blocque toujours sur
Pour le mettre avec un seul sed.
Code : Sélectionner tout - Visualiser dans une fenêtre à part #dnomcp=$(echo "${line:405:30}" | sed -e 's/[[:blank:]]*$//' | sed -e "s/'/''/g")
Merc à tous de votre aide.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 dnomcp=$(echo "${line:405:30}" | sed -e 's/[[:blank:]]*$//' | sed -e "s/'/''/g") # Devient : dnomcp=$(echo "${line:405:30}" | sed -e 's/[[:blank:]]*$//' -e "s/'/''/g")
Si le nom contient une apostrophe, le sed pose problème ! (pour N'Guyen, par exemple), Sinon on peut éviter l'appel à awk avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part nom=$(echo "${line:56:60}" | awk 'BEGIN{FS="/"} {print $1}' | sed -e "s/'/''/g")
puis :
Code : Sélectionner tout - Visualiser dans une fenêtre à part nom=${line:56:60}; nom=${nom%/*}
Sinon, quel est le but de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 prenom=$(echo "${line:56:60}" | awk 'BEGIN{FS="/"} {print $2}') # devient prenom="${line:56:60}"; prenom=${nom#*/}Ce serait intéressant à contourner
Code : Sélectionner tout - Visualiser dans une fenêtre à part sed -e "s/'/''/g"
Le code
Merci Encore une seconde de gagner. (8=>3)
Avez vous d'autre idées? Merci de votre au final je vais gagner quelque heure de traitement de fichier.
Tio
Ça pourrait être intéressant de poster quelques lignes du fichier source et le résultat escompté.
140001D00110014421MB2TCLP 112 DE BREVEDENT D ABLON/ARLETTE JEANNE ALBERTE MARIE 9792 LE CHATEAU 14600 ABLON 14 14600 MMECLERET DE LANGAVANT MICHEL 09/03/193214 ABLON NEEDE BREVEDENT D ABLON ARLETTE JEANNE 11 100064108063A 1404421
140001D00111014421MB2TCLPI112 DE BREVEDENT D ABLON/ARLETTE JEANNE ALBERTE MARIE 9792 LE CHATEAU 14600 ABLON 14 14600 MMECLERET DE LANGAVANT MICHEL 09/03/193214 ABLON NEEDE BREVEDENT D ABLON ARLETTE JEANNE 11 100064108063A 1404421
140001D00111024421MB2TCQPI011 CLERET DE LANGAVANT/OLIVIER RAPHAEL MARIE 9292 0006 RUE TOULLIER 75005 PARIS 7581050021293550006 75005 M CLERET DE LANGAVANT OLIVIER RAPHAEL10/02/195714 DEAUVILLE 11 100054343789A 1404421C'est assez trivial, l'objet est de saisir une base de données; Mon script pour le lancement sql est déjà optimisé.SET DATEFORMAT DMY;
INSERT INTO [TESTCad_NORM09].[dbo].[Personnes] ([Majic3_Code], [Civilite_Code],[Nom],[Prenom],[Representant],[AdresseL1],[AdresseL2],[AdresseL3],[CodePostal],[Commune_Nom],[Pays_Code],[Adresse_Exacte],[DateNaissance],[NomEpx] ,[PrenomEpx] ,[FrmJur_Code] ,[CRPF_ID] ,[DateCreation] ,[DateModification] ,[AuteurCreation] ,[AuteurModification] ,[tmpClePropri]) VALUES ('MB2TCL','MME','DE BREVEDENT D ABLON','ARLETTE JEANNE ALBERTE MARIE',NULL,'LE CHATEAU',NULL,NULL,'14600','ABLON','F',1,cast('09/03/1932 00:00:00' AS DATETIME),NULL,NULL,'P',14,CURRENT_TIMESTAMP,NULL,'RL',NULL,NULL);
INSERT INTO [TESTCad_NORM09].[dbo].[Personnes] ([Majic3_Code], [Civilite_Code],[Nom],[Prenom],[Representant],[AdresseL1],[AdresseL2],[AdresseL3],[CodePostal],[Commune_Nom],[Pays_Code],[Adresse_Exacte],[DateNaissance],[NomEpx] ,[PrenomEpx] ,[FrmJur_Code] ,[CRPF_ID] ,[DateCreation] ,[DateModification] ,[AuteurCreation] ,[AuteurModification] ,[tmpClePropri]) VALUES ('MB2TCL','MME','DE BREVEDENT D ABLON','ARLETTE JEANNE ALBERTE MARIE',NULL,'LE CHATEAU',NULL,NULL,'14600','ABLON','F',1,cast('09/03/1932 00:00:00' AS DATETIME),NULL,NULL,'P',14,CURRENT_TIMESTAMP,NULL,'RL',NULL,NULL);
INSERT INTO [TESTCad_NORM09].[dbo].[Personnes] ([Majic3_Code], [Civilite_Code],[Nom],[Prenom],[Representant],[AdresseL1],[AdresseL2],[AdresseL3],[CodePostal],[Commune_Nom],[Pays_Code],[Adresse_Exacte],[DateNaissance],[NomEpx] ,[PrenomEpx] ,[FrmJur_Code] ,[CRPF_ID] ,[DateCreation] ,[DateModification] ,[AuteurCreation] ,[AuteurModification] ,[tmpClePropri]) VALUES ('MB2TCQ','M','CLERET DE LANGAVANT','OLIVIER RAPHAEL MARIE',NULL,'0006 RUE TOULLIER',NULL,NULL,'75005','PARIS','F',1,cast('10/02/1957 00:00:00' AS DATETIME),NULL,NULL,'P',14,CURRENT_TIMESTAMP,NULL,'RL',NULL,NULL);
Envoyé par Tiolebucheron
Ça fait le même chose, mais tient sur une ligne.
Code : Sélectionner tout - Visualiser dans une fenêtre à part for var in l2 l3 pc ville; do [ -z ${!var} ] && eval $var="NULL"; done
Il faut absolument éviter les appels à awk car c'est hyper gourmand (ou alors on fait tout le traitement avec un seul awk)
Et donc on peut remplacer
Par
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part nom=$(echo "${line:56:60}" | awk 'BEGIN{FS="/"} {print $1}')
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part nom=$(echo "${line:56:60}" | cut -d/ -f1)
Moins important mais à ne pas négliger: on peut aussi remplacer
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 if [ "$frmjur" = " " ] then frmjur="'P'" else if [ -z "$frmjur" ] then frmjur="NULL" else frmjur="'$frmjur'" fi fi
par
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 if [ "$frmjur" = " " ] then frmjur="'P'" elif [ -z "$frmjur" ] then frmjur="NULL" else frmjur="'$frmjur'" fi
Remplacer des conditions enchainées avec "||" par des "-o"
=> un seul appel à test au lieu de 3
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part if [ -z "$naissance" -o "$naissance" = " " -o "$naissance" = "00/00/0000" ]
Et (je l'ai raté mais j'aurais dû le dire hier) on peut remplacer chaque test simple, comme celui-ci
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 if [ -z "$ville" ] then ville="NULL" else ville="'$ville'" fi
Par un test encore plus simple
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part [ -z "$ville" ] && ville="NULL" || ville="'$ville'"
Et ptet essayer de gagner en lisibilité en le mettant dans le sens logique
Car il semble naturel d'espérer plus de présences que d'abscences.
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part [ -n "$ville" ] && ville="'$ville'" || ville="NULL"
Maintenant, on peut aussi envisager un changement radical en réécrivant tout le script en Python. La première fois que j'ai essayé, j'avais un script shell qui convertissais un gros fichier texte en fichier XML. Ca marchait mais le script mettait 30mn pour tout parser.
Je l'ai réécrit en Python => le traitement a duré moins de 2mn. Ce jour là, je me suis mis définitivement à Python...
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
J'ai lu en diagonale. S'il s'agit bien de parser un fichier à champs de longueur fixe, GNU awk dispose d'une variable builtin particulièrement efficace pour ce genre de problème.
http://www.gnu.org/software/gawk/man...#Constant-Size
Ça sera plus efficace que de traverser un fichier avec un read.
Merci pour tous ces renseignements
Pour la dernière fonction c'est trop compliqué pour moi et pour python encore plus et pas trop le temps
Encore un renseignement
Je cherche à tester la chaine de caractère contenant la date. exemple '12/12/1979". Il y a des dates erronées 30/02/1930 ou encore 00/00/1950.
Existe-il un format date en bash permettant de tester?
Merci de votre aide
Tio
Si j'ai le temps cet aprem je te porterai ton script et tu verras la simplicité
Désolé, le bash ne connait que le texte. Si tu veux tester, il te faut faire une fonction adaptée
Exemple de fonction qui décompose une chaine jj/mm/aaaa
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 verifDate() { jj=`echo $1 |cut -d/ -f1` mm=`echo $1 |cut -d/ -f2` aa=`echo $1 |cut -d/ -f3` # Plus qu'à vérifier la validité de $jj, $mm et $aa }
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Partager