#1 Le 19/09/2020, à 11:05
- Hizoka
Ajouter un numéro à des dossiers
Bonjour à vous
J'ai récupéré une tache pro qu'un collègue n'arrivait pas à accomplir.
J'ai plus ou moins réussi mais j'aimerais votre avis pour voir si je ne suis pas passé à coté d'un truc, voir si on peut l'améliorer et un un peu pour le fun aussi
L'idée du truc, on a récupéré une arborescence de plusieurs 10e de milliers de dossiers.
Les dossiers sont globalement ainsi :
Clients/A/Amant Jean (bli)/...
Clients/D/Dupont Alain (bla)/...
Mais évidemment, ça serait trop simple si tout était bien tenu
Il y a donc des fautes de frappes :
Clients/A/Armant Jean (bli)/...
Des inversions Nom / Prenom
Clients/A/Jean Amant (bli)/...
Des clients sans prénom
Clients/A/Amant (bli)/...
Des sortes de dossiers doublons
Clients/A/Jean Amant (bli)/...
Clients/A/Jean Amant (blu)/...
Clients/A/Jean Amant (bli)/...
Clients/Agence X/A/Jean Amant (bli)/...
Des clients sans parenthèses
Clients/A/Jean Amant/...
Et d'autres trucs que je n'ai peut être pas identifié XD
J'ai un fichier clients.csv qui contient une liste d'environ 10 000 clients de type :
Nom;Prenom;Code client
Amant;Jean;4569
Dupont;Alain;25898
...
Le truc, c'est qu'on veut ajouter le numéro du client dans le nom du dossier pour éviter de les confondre avec des homonymes, des fautes de frappes...
Ce qui donnerait :
Clients/A/Amant Jean (bli)__4569/...
Clients/D/Dupont Alain (bla)__25898/...
On les ajoute à la fin pour ne pas perturber leur classement actuel.
Afin de faciliter le travail, j'ai listé l’arborescence des dossiers dans un fichier texte afin de ne pas exécuter des find à tout bout de champ mais plutôt des grep.
Mon fichier Arbo.txt ressemble à ça :
Clients/A/Amant Jean (bli)@@@Clients/A/AmantJean(bli)
Clients/D/Dupont Alain (bla)@@@Clients/D/DupontAlain(bla)
Tout ce qui se trouve à droite des @@@ est l'adresse mais avec suppression des espaces, des tirets, des underscores et remplacement des accents par leurs lettres normales.
Ceci afin d'éviter de passer à côté d'un dossier pour une question d'espace ou de tiret ou d'utilisation d'accent.
Car en effet, si dans clients.csv le nom contient un accent mais pas dans le nom du dossier associé, alors on passerait à coté, de même avec un prénom composé qui aurait une fois un - et une fois un espace.
Il ne reste plus qu'à boucler sur le fichier clients.csv et de faire un grep avec le nom et le prénom du client sur le fichier Arbo.txt.
Mais il faut faire tout une succession de grep pour ne pas passer à côté de dossiers ou ne pas confondre de nom (genre on veut Dupont Alain et pas Dupontel Alain).
Afin de voir ce que ça donnera avant de me lancer dedans, je crée un fichier Retours.csv.
Voici donc mon script, donnez vos avis, vos améliorations... et surtout les cas que j'aurais potentiellement pu zapper...
# Ma petite fonction de nettoyage des caractères spéciaux
function Nettoyage
{
sed "s/[[=e=]]/e/g; s/[[=a=]]/a/g; s/[[=y=]]/y/g; s/[[=u=]]/u/g; s/[[=i=]]/i/g; s/[[=o=]]/o/g; s/[[=c=]]/c/g; s/[-_ ']//g; s/\t//g; s/\n//g; s/\r//g" <<< "${1}"
}
function LetsGo
{
echo "État|Nom|Prénom|Chrono|Adresse actuelle|Nouvelle adresse" > Retours.csv
while IFS=";" read Nom Prenom Chrono
do
# Si pas de prénom, on saute le client car c'est un établissement
[[ -z ${Prenom} || ${Prenom} == '' ]] && continue
# Suppression des caractères spéciaux du chrono
Chrono="${Chrono//$'\n'}"
Chrono="${Chrono//$'\r'}"
# Nettoyage du nom et prenom afin qu'ils correspondent à la partie à droite des @@@ du fichier Arbo.txt
NewNom=$(Nettoyage "${Nom}")
NewPrenom=$(Nettoyage "${Prenom}")
# Nom Prenom
# Logiquement, aucun doute dessus sauf en cas d'homonyme exact => Il faudra donc que je les recherche avant
# ex : Amant Jean (bla) ou Amant Jean
# En cas de dossiers multiple, il faudra une confirmation manuelle
NbDossier=$(grep -ic "/${NewNom}${NewPrenom}(\|/${NewNom}${NewPrenom}$" Arbo.txt)
# On a trouvé 1 dossier correspondant
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/${NewNom}${NewPrenom}(\|/${NewNom}${NewPrenom}$" Arbo.txt)
echo "Nom Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - Nom Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/${NewNom}${NewPrenom}(\|/${NewNom}${NewPrenom}$" Arbo.txt)
continue
fi
# Prenom Nom
# Dans le cas ou le prénom et le nom ont été inversés
# ex : Jean Amant (bla) ou Jean Amant
# Nécessite vérification manuelle
NbDossier=$(grep -ic "/${NewPrenom}${NewNom}(\|/${NewPrenom}${NewNom}$" Arbo.txt)
# On a trouvé 1 dossier correspondant
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/${NewPrenom}${NewNom}(\|/${NewPrenom}${NewNom}$" Arbo.txt)
echo "Prénom Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - Prénom Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/${NewPrenom}${NewNom}(\|/${NewPrenom}${NewNom}$" Arbo.txt)
continue
fi
# Nom .* Prenom
# Dans le cas où il y a quelque chose entre le nom et le prénom
# Nécessite vérification manuelle
# Amantt Jean : Faute de frappe ou autre client ?
# Amant Jean Claude : Ce n'est sûrement pas le même client
# Amant (Dupont) Jeanne : Contient le nom de jeune fille
NbDossier=$(grep -ic "/${NewNom}.*${NewPrenom}(\|/${NewNom}.*${NewPrenom}$" Arbo.txt)
# On a trouvé 1 dossier
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/${NewNom}${NewPrenom}(\|/${NewNom}${NewPrenom}$" Arbo.txt)
echo "Nom ~ Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - Nom ~ Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/${NewNom}${NewPrenom}(\|/${NewNom}${NewPrenom}$" Arbo.txt)
continue
fi
# Prenom .* Nom
# Dans le cas où il y a quelque chose entre le prenom et le nom et qu'ils ont été inversés
# Nécessite vérification manuelle
# Jeanne Amant : Ce n'est sûrement pas le même client
# Jeanne Dupont (Amant) : Contient le nom de femme
NbDossier=$(grep -ic "/${NewPrenom}.*${NewNom}(\|/${NewPrenom}.*${NewNom}$" Arbo.txt)
# On a trouvé le dossier
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/${NewPrenom}.*${NewNom}(\|/${NewPrenom}.*${NewNom}$" Arbo.txt)
echo "Prénom ~ Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - Prénom ~ Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/${NewPrenom}.*${NewNom}(\|/${NewPrenom}.*${NewNom}$" Arbo.txt)
continue
fi
# .* Nom .* Prenom
# Nécessite vérification manuelle
# Dans le cas ou c'est le nom de jeune fille qui est connu et qu'il est entre ()
# Dupont (Amant) Jeanne : Contient le nom de femme
NbDossier=$(grep -ic "/.*${NewNom}.*${NewPrenom}\|/.*${NewNom}.*${NewPrenom}$" Arbo.txt)
# On a trouvé le dossier
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/.*${NewNom}.*${NewPrenom}\|/.*${NewNom}.*${NewPrenom}" Arbo.txt)
echo "~ Nom ~ Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - ~ Nom ~ Prénom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/.*${NewNom}.*${NewPrenom}\|/.*${NewNom}.*${NewPrenom}" Arbo.txt)
continue
fi
# Nom
# Nécessite vérification manuelle
# Si seul le nom et présent
NbDossier=$(grep -ic "/${NewNom}(\|/${NewNom}$" Arbo.txt)
# On a trouvé 1 dossier correspondant
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/${NewNom}(\|/${NewNom}$" Arbo.txt)
echo "Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - Nom|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/${NewNom}(\|/${NewNom}$" Arbo.txt)
continue
fi
# ~ Nom ~
# En désespoir de cause
# Si seul le nom et présent
NbDossier=$(grep -ic "/.*${NewNom}" Arbo.txt)
# On a trouvé 1 dossier correspondant
if [[ ${NbDossier} -eq 1 ]]
then
Dossier=$(grep -i "/.*${NewNom}" Arbo.txt)
echo "~ Nom ~|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}|${Dossier%%@@@*}__${Chrono}" >> Retours.csv
continue
# On a trouvé plusieurs dossiers
elif [[ ${NbDossier} -gt 1 ]]
then
while read Dossier
do
echo "Multi - ~ Nom ~|${Nom}|${Prenom}|${Chrono}|${Dossier%%@@@*}" >> Retours.csv
done < <(grep -i "/.*${NewNom}" Arbo.txt)
continue
fi
# Aucun résultat
echo "Introuvable|${Nom}|${Prenom}|${Chrono}" >> Retours.csv
done < Clients.csv
}
Merci à vous et bon week end
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#2 Le 19/09/2020, à 15:44
- kamaris
Re : Ajouter un numéro à des dossiers
Une remarque sur les grep : deux tiers d'entre eux peuvent être évités par l'usage de tableaux :
mapfile -t Dossiers < <(grep -i "…" Arbo.txt)
NbDossiers=${#Dossiers[@]}
Sinon je crois que tu attrapes les fautes de frappe sur le nom en ne cherchant que le prénom, et vice versa.
Donc tu loupes potentiellement des cas, par exemple si seul le nom est présent et qu'il y a une faute de frappe dessus.
Il ne faut peut-être pas pousser, mais le cas général serait de rechercher les noms à une distance de Levenshtein de 1 (ou plus…) du nom de référence : il y a des algos pour ça…
Hors ligne
#3 Le 21/09/2020, à 08:40
- Hizoka
Re : Ajouter un numéro à des dossiers
Merci Karamis
Pour mapfile, j'étais persuadé qu'il ne fonctionnait pas sous bash 4.4... mais en fait si, du coup je vais l'utiliser
J'adore cette commande.
Ouais ça devient compliqué...
Il va falloir qu'ils assument leurs erreurs...
Je vais leur lister les erreurs et doutes...
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne