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

  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
    3 010
    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 : 3 010
    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 730
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 730
    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 ?!

  5. #5
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 418
    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 418
    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).

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 010
    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 : 3 010
    Par défaut
    Exact, donc le switch -o et l'utilisation de wc -l est une meilleur option.

  7. #7
    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.

  8. #8
    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 : 42
    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
    ?

  9. #9
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Citation Envoyé par balkany Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F'mot' '/truc/{print n; exit} /^[^#]*mot/{sub("#.*",""); n+=NF-1}' fichier
    ?
    Hello

    Merci de ton aide.

    Je viens de tenter la commande, hélas cette dernière me renvoie aucune réponse. Du moins, j'ai un blanc en retour.
    Qu'est ce que cela devrait renvoyer stp ?

  10. #10
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Si ça n'a rien affiché, c'est qu'il n'y a pas de « balise fermante » truc dans ton fichier.
    Si on veut afficher quand même un résultat dans ce cas (bien qu'il ait alors peu de sens au vu de la question posée), on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F'mot' '/truc/{b=1; print n; exit} /^[^#]*mot/{sub("#.*",""); n+=NF-1} END{if (!b) print n}' fichier

  11. #11
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Je crois avoir trouvé !
    Si jamais "mot", "truc"... bref les mots clés ne sont pas toujours écrit de la même manière...
    Si on veut chercher mot mais sans se soucier de la casse, y aurait il quelque chose à faire dans la commande stp ?

    Merci d'avance

  12. #12
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Pour ignorer la casse, il y a la variable IGNORECASE de gawk :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk -F'mot' 'BEGIN{IGNORECASE=1} /truc/{b=1; print n; exit} /^[^#]*mot/{sub("#.*",""); n+=NF-1} END{if (!b) print n}' fichier
    Après, truc et mot peuvent être n'importe quelle expression régulière…

  13. #13
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Ca marche !!

    Merciiiii

    Question : Est ce que l'ensemble de la recherche ignore la casse où seulement le "mot" svp ?
    J'essaie d'ajouter une condition à présent à exclure supplémentaire mais ça n'a pas l'air de fonctionner :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gawk -F'mot' 'BEGIN{IGNORECASE=1} /truc/{b=1; print n; exit} /^[^#]*mot/{sub("#.*",""); n+=NF-1} /^bidule*mot/{sub("#.*",""); n+=NF-1} END{if (!b) print n}' fichier

  14. #14
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Tu casses toute la logique du truc là
    Le séparateur de champs et le mot recherché doivent ne faire qu'un pour que ça marche…

    Sinon pour ta question, la lecture de man gawk peut être utile :
    If IGNORECASE has a non-zero value, then string comparisons and pattern matching in rules, field splitting with FS and FPAT, record separating with RS, regular expression matching with ~ and !~, and the gensub(), gsub(), index(), match(), patsplit(), split(), and sub() built-in functions all ignore case when doing regular expression operations.

  15. #15
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Donc si je comprends bien, pas moyen d'exclure deux combinaisons pour que cela fonctionne ?
    N'y a t'il pas un moyen ?

  16. #16
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Je ne comprends plus ce que tu veux faire : tu devrais repartir d'un exemple clair avec une demande claire, comme au début de ton message #7.

  17. #17
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Je comprends, je recommence

    Mon fichier à analyser :

    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
    bidule 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é ni utilisé après l'instruction bidule.
    Le résultat dans cet exemple doit retourner 2

  18. #18
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Ok, alors le problème n'est pas tant au niveau du filtrage des lignes qu'au niveau de ce qu'on doit leur enlever.
    D'ailleurs, il vaut mieux carrément faire sauter le filtre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gawk -F'mot' 'BEGIN{IGNORECASE=1} /truc/{b=1; print n; exit} {sub("#.*|bidule.*",""); if (NF) n+=NF-1} END{if (!b) print n}' fichier

  19. #19
    Membre éclairé
    Inscrit en
    Avril 2008
    Messages
    369
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 369
    Par défaut
    Encore merci pour l'aide, j'apprécie vraiment !

    Bon... par contre, ce code me renvoie 0, ce qui n'est pas normal.
    Il ne manque pas un ^ ?

  20. #20
    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 : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    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
    $ cat fichier
    blabla
    blabla
    blabla
    #mot
    blabla#mot
    mot
    bidule mot
    mot
    truc
    mot
    blabla
    $ gawk -F'mot' 'BEGIN{IGNORECASE=1} /truc/{b=1; print n; exit} {sub("#.*|bidule.*",""); if (NF) n+=NF-1} END{if (!b) print n}' fichier
    2
    $

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

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, 11h40
  2. Réponses: 2
    Dernier message: 03/05/2010, 17h11
  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, 16h58
  4. Réponses: 4
    Dernier message: 16/12/2005, 20h36
  5. Réponses: 9
    Dernier message: 22/11/2005, 22h20

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