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

Shell et commandes GNU Discussion :

tri et selection en langage awk


Sujet :

Shell et commandes GNU

  1. #21
    Membre éclairé Avatar de étoile de mer
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    978
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 978
    Par défaut
    un ami a essayé cette commande et ca marché nikel mais chez moi ca genere une erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    awk -F"(" '{printf "%s|%f\n", $0,substr($2,1,length($2)-1)}' monFicher | awk -F"-->" '{printf "%s|%s\n",$0, $1}' | sort -t"|" -k3 -k2.rn
    peut etre parceque je suis sous linux et lui sous unix
    il affiche cette erreur

    sort: adresse relative du caractère est zéro: invalid field specification `2.0rn'

  2. #22
    Membre expérimenté
    Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2007
    Messages : 248
    Par défaut
    Ah s'il on peut utiliser sort....alors ce n'est plus du tri en awk !

  3. #23
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonjour,

    Étoile de mer, l'énoncé de ton problème est pour le moins absconse. Je vais donc essayer d'en faire un résumé, tu me diras si je me trompe et le cas échéant, où.

    Il existe un fichier de la forme suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    insister->to put        -3.553851e-05
    insister->to vote       -7.547198e-06
    insister->to respect    -1.091798e-05
    joindre->to join        -2.994884e-06
    joindre->to alter        2.090002e-06
    Il faut le trier suivant la première colonne puis suivant la troisième (qui est numérique, en notation scientifique). La solution doit utiliser la commande awk. Est-ce bien cela? Je suppose que le caractère de séparation des colonnes est l'espace, c'est-à-dire que le premier champ de la première ligne est: "insister->to", le second "put" et le troisième "-3.553851e-05".

    Le big problème ici est de mélanger les tris alphabétique (première colonne) et le tri numérique (troisième colonne) le tout dans une seule commande de tri. La commande sort s'en sort (hé hé!) en partie mais n'est pas capable de mixer la manière de trier.

  4. #24
    Rédacteur

    Avatar de ok.Idriss
    Homme Profil pro
    IS Consultant
    Inscrit en
    Février 2009
    Messages
    5 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : IS Consultant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 5 220
    Par défaut
    Salut.

    Pour se fichier là, j'avais trouvé un moyen :

    - calcul des valeurs en notation scientifique
    - tri à bulle dans l'ordre décroissant des valeurs (stockage des lignes du fichier en fonction de cet ordre dans un tableau).
    - enregistrement dans un fichier intermédiaire et triage avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cat fichierIntermédiaire | grep joindre > fichierSortie
    cat fichierIntermédiaire | grep insister >> fichierSortie
    Au final j'avais ce code un peut lourd :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    #!/bin/bash
     
    if [ $# -lt 2 ]
    then
        printf "Saisir fichier d'entrée : "
        read fichierEnt
        printf "Saisir fichier de sortie : "
        read fichierSort
    else
        fichierEnt=$1
        fichierSort=$2
    fi
     
    fichierInt=fichier_int
     
    ExPow ()
    {
        exp=$(echo "(1*2.718281828459)" | bc) 
        value=1
        x=$1
        if [ $x -lt 0 ]
        then
            x2=$(echo $x | awk 'BEGIN{FS="-"} {print $2}')
        else
            x2=$x
        fi
     
        for (( i=1 ; i<=x2 ; i++ ))
        do
            value=$(echo "$value*$exp" | bc -l)
        done
        if [ $x -lt 0 ]
        then
            value=$(echo "1/$value" | bc -l)
        fi
    }
    k=0
     
    cat $fichierEnt | while true
    do
        read ligne
        if [ "$ligne" = "" ]
        then
            # tri à bulle
            for (( m=0 ; m<k ; m++ ))
            do
                let k2=$k-$m
                for (( n=0 ; n<k2 ; n++ ))
                do
                    comp=$(echo "${tab[n]} < ${tab[m]}" | bc)
                    if [ $comp -eq 1 ]
                    then
                        tampon1=${tab[m]}
                        tampon2=${tab2[m]}
     
                        tab[m]=${tab[n]}
                        tab2[m]=${tab2[n]}
     
                        tab[n]=$tampon
                        tab2[n]=$tampon2
                    fi
                done
                l=0
                until [ $k -eq 0 ] || [ $l -eq 100 ]
                do
                    let k=$k-1
                    echo ${tab2[k]} >> $fichierInt
                    let l=$l+1
                done
     
            done
            exit
        else
            set -- $ligne
            x=$(echo $3 | awk 'BEGIN{FS="e"} {print $2}')
            value2=$(echo $3 | awk 'BEGIN{FS="e"} {print $1}')
            x=$(echo $x | bc -l)
            ExPow $x
            tab[k]=$(echo "$value*$value2" | bc -l)
            tab2[k]=$(echo $ligne)
            let k=$k+1    
        fi
    done
     
    cat $fichierInt | grep insister > $fichierSort
    cat $fichierInt | grep joindre >> $fichierSort
    rm $fichierInt
    Mais cela fonctionnait parfaitement jusqu'au moment ou Étoile de mer me dit que le format de fichier à changé et est comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    a du-->expanding(1.223293e-02)
    a du-->genetically(1.223293e-02)
    a du-->barriers(3.153879e-02)
    a du-->oil(1.223293e-02)
    a du-->shape(1.223293e-02)
    a du-->contained(1.223293e-02)
    a du-->analysis(1.223293e-02)
    a du-->person(1.223293e-02)
    a du-->demands(3.153879e-02)
    a du-->code(1.223293e-02)
    a du-->agree(3.153879e-02)
    a du-->broadcasting(1.223293e-02)
    a du-->procurement(1.223293e-02)
    Et qu'il faut toujours trier dans l'ordre décroissant puis en fonction des termes de la ligne en précisant que le fichier peut faire 3GO et que les premiers termes sont inconnus . J'ai pas eu le temps de me pencher sur le problème de plus près ...

  5. #25
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonsoir ok.Idriss,

    Tu as effectivement passé beaucoup de temps sur ce problème flou et fluctuant. Sans indication précise, l'on peut se perdre en conjectures. Mais le problème est intéressant, à tout le moins. Alors imaginons une simplification de l'énoncé afin de trouver une solution satisfaisante:

    Supposons que le fichier d'entrée soit formaté comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Z    3.3333E-05
    B   -2.9876E-06
    A   -3.5790E-06
    B   -1.2345E-06
    Il faut que le fichier de sortie soit trié comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    A   -3.5790E-06
    B   -1.2345E-06
    B   -2.9876E-06
    Z    3.3333E-05
    Le tri des lignes est d'abord effectué sur le premier champ (A, B...) par ordre alphabétique croissant, et puis s'il y a plusieurs lettres identiques, les lignes sont triées sur le second champ par ordre numérique décroissant (pour la lettre B: -1...E-06, -2...E-06).

    Voici le code qui fait les deux tris, en passant pour chaque ligne par un fichier intermédiaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    LC_ALL="C"
    rm -f file_tmp file_out
    sort -k 1,1 file_in | awk '
    {
      print $0 >> "file_tmp"; close("file_tmp")
      if ($1 != prev)
      {
        system("sort -n -k 2,2 file_tmp >> file_out; rm file_tmp")
      }
      prev = $1
    }
    END {system("[ -e file_tmp ] && sort -n -k 2,2 file_tmp >> file_out")}'
    Pour être sûr que la commande sort fonctionne correctement, LC_ALL est forcé à "C"; ainsi, pas de problème avec le point au lieu de la virgule et autres joyeusetés.

  6. #26
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonjour,

    Une erreur aux limites s'est subrepticement glissée dans mon code. Mea culpa. Voici la correction. Si vous en repérez d'autres, faites m'en part!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    LC_ALL="C"
    rm -f file_tmp file_out
    sort -k 1,1 file_in | awk '
    function appendFile()
    {
      system("if [ -e file_tmp ]; then sort -n -k 2,2 file_tmp >> file_out; rm file_tmp; fi")
    }
    {
      if ($1 != prev) {appendFile()}
      print $0 >> "file_tmp"; close("file_tmp")
      prev = $1
    }
    END {appendFile()}'
    Maintenant la logique est plus claire (enfin j'espère!).

  7. #27
    Membre éclairé Avatar de étoile de mer
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    978
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 978
    Par défaut
    Merci Jimelyn,
    le travail a été rendu et j'etais obligé de le faire en C
    Merci

  8. #28
    Rédacteur

    Avatar de ok.Idriss
    Homme Profil pro
    IS Consultant
    Inscrit en
    Février 2009
    Messages
    5 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : IS Consultant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 5 220
    Par défaut
    Citation Envoyé par étoile de mer Voir le message
    j'etais obligé de le faire en C
    C'est peut être pas plus mal ...

Discussions similaires

  1. tri par selection
    Par houdabouayed dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 27/01/2007, 15h01
  2. Problème tri tutoriel selection multiple
    Par qbihlmaier dans le forum Access
    Réponses: 24
    Dernier message: 14/03/2006, 12h24
  3. TRI ET SELECTION DE CODE ALPHANUMERIQUE
    Par janpi34 dans le forum SQL
    Réponses: 2
    Dernier message: 07/05/2004, 19h41
  4. [langage] awk et sed dans script perl
    Par scoti dans le forum Langage
    Réponses: 3
    Dernier message: 07/04/2003, 19h26

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