IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

sed et boucle pour pour supprimer des lignes


Sujet :

Linux

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Par défaut sed et boucle pour pour supprimer des lignes
    Bonjour,

    J'ai un problème que je n'arrive pas à trouver sous la ligne de commande.
    Alors voilà je dois supprimer des lignes dans un fichier clients en me référant à une base interdite. Je pensais tenir le bon bout mais je suis en traine de me noyer.

    Admettons que j'ai un fichier client comme ceci (séparation par des ; ):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT2;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT3;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT6;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE
    avec un fichier interdit (le code du client avec un ; ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CLIENT2;
    CLIENT3;
    CLIENT6;
    Je veux avoir comme résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE
    et donc supprimer les occurences correspondantes trouver dans le fichier intedit.

    Sous bash j'essaye de faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for i in `cat interdit.txt`; do sed -i "/^$i/d" Clients.txt; done;
    Bon ça ne marche pas vraiment. Je ne sais pas pourquoi pas tous les codes clients commençant par A sont supprimés alors qu'il devrait en rester. En plus c'est très long (bon ok il y a 200 000 clients...)

    Rem1: Je n'arrive pas à faire la négation dans les options de sed ce qui me permettrai de me baser en fait que sur les bons codes et éviter de sortir une base interdite.

    Rem2: Je me demande s'il n'y a pas de prob avec le $ qui est un opérande particulier sous sed... C'est pour ça que j'ai mis entre " "

    Rem3: Je ne sais si c'est aussi possible de dire à sed de s'arrêter une fois la ligne supprimée car comme c'est une base client ben tous les codes sont différents... et çe me ferais gagner du temps.

    Rem4: Le code client est sur 6 caractères alpha mais ne prend pas forcément tous les caractères (par AA1 , CCC88 , AB , AZREKK).

    Rem5: Dans ma base interdite j'ai rajouté en fin de ligne pour chaque code un point virgule pour me faciliter la vie dans les comparaisons sinon j'avais encore plus de bordel. Donc il cherche le code client plus ;

    Rem6: ça commence toujours par le code direct d'où le ^

    Vous pouvez m'aider? Je me demande s'il ne faut pas que le fasse avec perl dans un plus gros prog.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Par défaut
    Rem7: le code client peut contenir des points à la suite ou pas (A.DRE. ou A..RF1) des apostrophes( L'ERMO ), des tirets (DU-CLI)

  3. #3
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    R1 : c'est ! (à mettre après le sélecteur de lignes)

    R2 : Non ! C'est le shell qui fait l'expansion de $i. Sed ne connait pas (pour t'en convaincre, remplace sed par echo).

    R3 : Oui. C'est la commande q.


    Comme tu parles d'optimisation, pourrais-tu donner les ordres de grandeurs (nombre de lignes) pour les 2 fichiers ?

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Par défaut
    j'ai déjà essayé avec ! mais ça me jette. Je n'ai pas du le placer au bon endroit surement. Je vais revoir ça.

    C'est ce que j'ai fait pour $i. Comme ça ne marchait pas j'ai fait un echo en boucle pour voir ce que me donné
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for i in `cat interdit.txt`; do echo "$i"; done
    bon pas de prob forcément puis après j'ai voulu rajouter un ; en plus et là ça m'inverse les champs. $i est évalué après l'affichage de ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for i in `cat interdit.txt`; do echo "$i;"; done
    va me donner
    ;CLIENT1
    ;CLIENT2
    ...
    et donc c'est pour ça que j'ai intégré directement le ; dans le fichier interdit. Bon c'est pas ça le plus important.

    Base de grandeur:
    fichier clients: 200 000 lignes
    fichier intedit: 198 000 lignes
    ==> il n'y a donc que 2000 clients à garder... tu vois pourquoi je voudrai utiliser la négation.

  5. #5
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    OK.

    Pour sed :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sed "/^$i/!d"
    sed -n "/^$i/p"

    Puisque les fichiers sont gros, évite absolument de faire `cat ...`. Tout le fichier est chargé en mémoire avant de faire quoi que ce soit d'autre.

    Niveau algo : tu cherches à parcourir le 2e fichier pour chaque ligne du 1er fichier. D'où, complexité quadratique.

    Si tes fichiers sont triés, tu peux lire les deux fichiers en même temps (complexité linéaire) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    exec < fichier2
    exec 6<&0
    exec < fichier1
    while read line; do
        echo "1: $line"
        read line2 <&6
        echo "2: $line2"
    done
    Ca devrait t'aider...

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Par défaut
    merdi du coup de main mais...

    le ! avant le d j'avais déjà essayé et ça ne passe pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    bash: !d": event not found

  7. #7
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Et si tu lisais le message d'erreur... ?

    C'est pas un problème de sed, mais du shell. Utilise des simples quotes.

  8. #8
    Membre émérite Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Par défaut
    liste.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT2;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT3;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT6;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE
    interdit.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CLIENT2;
    CLIENT3;
    CLIENT6;
    Commande "join" :

    -v numéro
    Afficher sur la sortie standard, à la place du résultat habituel, une ligne pour chaque ligne du fichier numéro (1 ou 2), qui ne peut pas être appariée.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    join -t";" -v 1 liste.txt interdit.txt
    Résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Par défaut
    Bon merci à tous.

    Donc ça marche. Je vais voir avec join aussi (p'tain les boules... connaissez pas)

    Sinon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    cat mailing.sh
     
    #!/bin/bash
    while read line
    do
    temp=`grep "^$line" $2`
    echo $temp >> $3
    done < $1
    Utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ./mailing.sh ClientsStat.txt Clients.txt Mailing.txt
    rem: mon fichier client_interdit et devenu en fait client_ok car plus rapide à traiter forcément.

  10. #10
    Membre confirmé
    Inscrit en
    Juillet 2002
    Messages
    168
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 168
    Par défaut
    Citation Envoyé par BlaireauOne Voir le message
    liste.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT2;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT3;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT6;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE
    interdit.txt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CLIENT2;
    CLIENT3;
    CLIENT6;
    Commande "join" :

    -v numéro
    Afficher sur la sortie standard, à la place du résultat habituel, une ligne pour chaque ligne du fichier numéro (1 ou 2), qui ne peut pas être appariée.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    join -t";" -v 1 liste.txt interdit.txt
    Résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CLIENT1;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT4;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT5;NOM PRENOM;ADRESSE;CODE;VILLE
    CLIENT7;NOM PRENOM;ADRESSE;CODE;VILLE
    intéressant le join je l'ai oublié, merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Une boucle pour supprimer des lignes ?
    Par eldoir dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 08/04/2012, 18h43
  2. Réponses: 3
    Dernier message: 25/12/2009, 09h29
  3. problème pour supprimer des lignes d'un fichier
    Par NicoO_O dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 17/01/2008, 07h23
  4. Réponses: 2
    Dernier message: 13/11/2007, 10h19
  5. Shell pour supprimer des lignes d'un fichier
    Par nelsa dans le forum Autres langages
    Réponses: 2
    Dernier message: 20/09/2004, 12h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo