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 :

Nombre de fois où une chaine de caractères est mentionnée dans un fichier


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut Nombre de fois où une chaine de caractères est mentionnée dans un fichier
    Bonjour,

    Je pense que le titre est parlant mais...
    Je cherche à connaitre le nombre de fois où une chaîne de caractère est présente dans un fichier donné.
    Je débute dans le sujet des shells et si vous pouvez m'aider svp, ce serait super ^^

    Problème mon shell dans mon cas devrait retourner 6 mais il retourne 1 et je suis bloqué.

    Pour cela, mon shell qui prend en entrée l'écran dans lequel je souhaite faire la recherche ($1) et $2 est la chaîne que je recherche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ecran="$1"
     
    SOURCES=$SOURCES/$ecran
     
    echo grep -o $2 $SOURCES|wc -l
    Un énorme merci par avance

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    echo est la commande la plus basique qui soit. Si tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo grep bidule machinchose.txt
    elle affichera grep bidule machinchose.txt et pas du tout le résultat de la commande grep. Si tu veux intégrer du code à évaluer dans un echo tu dois le mettre dans un sous-shell:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $(grep bidule machinchose.txt)
    grep affiche par défaut ses résultats, donc echo n'est pas nécessaire. De plus wc n'est pas utile non plus puisque grep dispose déjà du switch -c pour renvoyer le nombre de résultat.

    Pose toi aussi la question de la nature du paramètre $2: est-ce que tu veux que celui-ci soit évalué comme une pattern regex ou bien comme une chaîne littérale (grep a aussi une option pour ça).

    un man grep vaut mieux que deux tu l'auras.

  3. #3
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Merci pour ta réponse

    L'apprentissage est compliqué mais j'ai compris !

    J'ai à présent de premiers résultats grâce à toi

    Je suis toutefois confronté à un nouveau problème, je me permets de l'exposer

    Mon fichier comporte x fois la chaîne de caractère que je recherche, cependant au delà d'une certaine ligne je souhaite ne plus compter le fait de les trouver.
    Je cherche dans les options de grep mais je ne vois pas de solution...

    Aurais tu une idée stp par hasard ?

    Mon shell actuel :

    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
     
    motFin="INSTRUCTIONS"
    ecran=$1
     
    SOURCES=$(find $SOURCES -name $ecran)
     
    #Mode INT : Doit contenir tous les champs saisissables de l'écran (Formule : tous les formonly - Les LABEL définis avec un formonly)
    #Mode SOR : Doit contenir tous les champs que l'on affiche de l'écran (Formule : tous les formonly)
    if [ $2 = "INT" ]
    then
       tableauDeRecherche=("formonly" "LABEL.*formonly")
    else #SOR
       tableauDeRecherche=("formonly" )
    fi
     
    #Récupérer l'endroit au delà duquel on ne veut plus compter
    end="$(grep -n $motFin $SOURCES | sed 's/[^[:digit:]]//g')"
     
    #Parcours du tableau en fonction du mode de lancement
    for motRecherche in ${tableauDeRecherche[*]}
    do
    #echo $motRecherche;
     
    if [[ ! $result ]] #On se trouve dans le premier passage
    then
       result=$(grep -o $motRecherche $SOURCES|wc -l)
    else
       result=$(($result-$(grep -o $motRecherche $SOURCES|wc -l)))
    fi
     
    done
     
    echo $result
    Merci par avance en tout cas

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 664
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 664
    Par défaut
    Bonjour,

    stocker le résultat d'une recherche de find dans une variable n'est peut-être pas une bonne idée : find peut retourner plusieurs résultats.

    le tableauderecherche est loin d'être indispensable. Par contre, en te renseignant sur les capacités des regex, tu trouveras comment indiquer plusieurs motifs dans une seule instruction.

    grep ne permet pas d'indiquer le terme de la recherche par rapport à un motif; sed oui.

    ton script pourrait donc ne pas être plus compliqué que : find ... -exec sed '...' {} | wc -l \;.
    ... étant les options/commandes adéquates.

    NB:
    mon shell [...] devrait retourner 6 mais il retourne 1
    comment peut-on en être certain : on ne dispose pas du fichier pour vérifier ?!
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Exemple de fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    blabla
    blabla
    blabla
    #mot
    blabla#mot
    mot
    mot
    mot
    truc
    mot
    blabla
    Ce que je veux que fasse mon script, c'est compter le nombre de fois où "mot" est présent avant l'instruction truc et où "mot" n'est pas diésé.

    Aujourd’hui, j'en suis là (mais j'ai un énorme problème avec le retour de mon instruction grep...
    Lorsque j'exécute la commande sur putty, les résultats du grep semble se succéder comme si elles étaient dans un tableau hors, dans le shell, je vois bien que ce n'est pas le cas.
    Je pense que si j'arrivais à récupérer le résultat pour le mettre dans un tableau (tabGrep), mon shell fonctionnerait.
    Quelqu'un aurait il une idée svp ?

    Voici le script actuel :

    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
     
     
    conditionSOR1="formonly"
    conditionSOR2="'#'.*formonly"
    conditionINT1="formonly"
    conditionINT2="'#'.*LABEL.*formonly"
    conditionINT3="LABEL.*formonly"
    motFin="INSTRUCTIONS"
    SOURCES=$(find $SOURCES -name $1)
     
    #Récupérer l'endroit au delà duquel on ne veut plus compter qui est deja unique
    end="$(grep -n $motFin $SOURCES | sed 's/[^[:digit:]]//g')"
     
    if [[ ! $result ]] #On se trouve dans le premier passage
    then
     
       if [ $2 = "INT" ]
       then
          tabGrep=$(grep -ion $conditionINT1 $SOURCES | grep -v $conditionINT2 $SOURCES | grep -v $conditionINT3 $SOURCES | sed 's/[^[:digit:]]//g')
       else #SOR
          tabGrep=$(grep -ion $conditionSOR1 $SOURCES | grep -v $conditionSOR2 $SOURCES | sed 's/[^[:digit:]]//g')
       fi
     
       for ligneRecherche in ${tabGrep[*]}
       do
          if [ "$ligneRecherche" -lt "$end" ]
          then
             result=$(($result+1))
          fi
       done
    fi
     
    echo $result

    Citation Envoyé par N_BaH Voir le message
    Bonjour,

    stocker le résultat d'une recherche de find dans une variable n'est peut-être pas une bonne idée : find peut retourner plusieurs résultats.

    le tableauderecherche est loin d'être indispensable. Par contre, en te renseignant sur les capacités des regex, tu trouveras comment indiquer plusieurs motifs dans une seule instruction.

    grep ne permet pas d'indiquer le terme de la recherche par rapport à un motif; sed oui.

    ton script pourrait donc ne pas être plus compliqué que : find ... -exec sed '...' {} | wc -l \;.
    ... étant les options/commandes adéquates.

    NB:
    comment peut-on en être certain : on ne dispose pas du fichier pour vérifier ?!
    Je t'avoue avoir pas mal chercher avec les indices que tu m'as laissé et je suis conscient qu'il y a certainement moyen de l'écrire de manière bien plus optimisé mais je ne vois vraiment pas :/
    Le débutant est dépassé mais ton aide est très sympa et bonne à prendre

    Merci à tous d'ailleurs.

  6. #6
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Citation Envoyé par drogba72 Voir le message
    Exemple de fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    blabla
    blabla
    blabla
    #mot
    blabla#mot
    mot
    mot
    mot
    truc
    mot
    blabla
    Ce que je veux que fasse mon script, c'est compter le nombre de fois où "mot" est présent avant l'instruction truc et où "mot" n'est pas diésé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F'mot' '/truc/{print n; exit} /^[^#]*mot/{sub("#.*",""); n+=NF-1}' fichier
    ?

  7. #7
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 358
    Par défaut
    Bonjour,
    Citation Envoyé par CosmoKnacki Voir le message
    De plus wc n'est pas utile non plus puisque grep dispose déjà du switch -c pour renvoyer le nombre de résultat.
    Ce n'est pas tout à fait vrai, le switch -c renvoie le nombre de lignes et non le nombre d'occurences (si le pattern est rencontré plusieurs fois sur une même ligne, celui-ci ne sera compté qu'une seule fois).

  8. #8
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Exact, donc le switch -o et l'utilisation de wc -l est une meilleur option.

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

Discussions similaires

  1. [Batch] Vérifier si une chaine de caractères est présente dans un fichier
    Par jp_____ dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 23/08/2013, 10h40
  2. Réponses: 2
    Dernier message: 03/05/2010, 16h11
  3. Tester le nombre de lettre d'une chaine de caractéres
    Par koKoTis dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 13/05/2007, 15h58
  4. Réponses: 4
    Dernier message: 16/12/2005, 19h36
  5. Réponses: 9
    Dernier message: 22/11/2005, 21h20

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