Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 19/09/2020, à 12:05

Hizoka

Ajouter un numéro à des dossiers

Bonjour à vous smile

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 smile

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 tongue
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 smile


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#2 Le 19/09/2020, à 16: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, à 09: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 smile
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