Forum Programmation.shell Faire un script reproduisant une commande

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
-1
5
déc.
2014

Bonsoir,

J'ai pour devoir de faire un script shell qui puisse reproduire le "makee" :

Voici mon sujet : http://img11.hostingpics.net/pics/785835cats.jpg
(désolé pour les liens je n'ai pas réussi a mettre les images
Et le fichier makefile pour les tests :
http://img11.hostingpics.net/pics/742520catsaa.jpg

Donc j'ai fait un script mais elle ne s'applique que pour la première ligne :

#!/bin/sh

if [ -e $1 ]
then
    AVANT=`cat $1 | grep -v '^#' | grep ':' | sed 's/\t//g' | cut -d ':' -f1 | head -1`
    APRES=`cat $1 | grep -v '^#' | grep ':' | sed 's/\t//g' | cut -d ':' -f2 | head -1`
    COMMANDE=`cat $1 | grep -v '^#' | grep -v ':' | sed 's/\t//g'| sed 's/ /:/g'`
    if [ -e $AVANT ]
    then   echo "$AVANT existe"
    else
        if [ ! -e $APRES ]
        then
            echo "$APRES n'existe pas"
            exit 1
        else
            for i in $COMMANDE
            do
                var=`echo $i | sed 's/:/ /g'`
                sh -c "$var"
            done
        fi
    fi
else
    echo "Fichier makefile inexistant"
fi

Je dois donc utiliser la récursivité mais je ne vois pas comment faire pour passer d'un bloc à l'autre.

  • # Récursivité

    Posté par  . Évalué à 2.

    Je dois donc utiliser la récursivité mais je ne vois pas comment faire pour passer d'un bloc à l'autre.

    Qui dit récursivité dit appel de la fonction par elle-même. Donc appel du makefile au sein du makefile. A priori, je ne vois pas cela dans votre script.

    Matricule 23415

    • [^] # Re: Récursivité

      Posté par  . Évalué à 2. Dernière modification le 06 décembre 2014 à 10:59.

      Pour le posteur initial : as-tu vu dans ton cours les notions de fonction en shell ?
      Sais-tu ce que fait "head -1" ?

      • [^] # Re: Récursivité

        Posté par  . Évalué à 1.

        J'ai modifié le script en prenant en considération tout les commentaires :

        #!/bin/sh
        if [ ! -e $1 ]
        then
            DEPENDANCES=`cat makefiletest | grep -v '^#' | grep '$1' | sed 's/\t//g' | c                        ut -d ':' -f2 | head -1`
            COMMANDE=`cat makefiletest | grep -v '^#' | grep -v ':' | sed 's/\t//g'| sed                         's/ /:/g'`
        
            for i in $DEPENDANCES
            do
                if [ -e $i ]
                then for k in $COMMANDE
                do
                    var=`echo $k | sed 's/:/ /g'`
                    echo $var
                    #sh -c "$var"
                done
                else
                    cat makefiletest | grep $i 2>&1 /dev/null
                    if [ $? -ne 0 ]
                    then
                        echo "prérequis $i inexistant"
                        exit 1
                    else
                        echo "STOP" <- Récursivité ici ?
                        exit 0
                    fi
                fi
            done
        else
        echo "La cible $1 existe deja"
        exit 0
        fi

        1) Comment je fait pour tester si $i se trouve en tant que cible ? ( Par exemple tester si toto.o se trouve en tant que cible )

        cat makefiletest | grep $i 2>&1 /dev/null
        if [ $? -ne 0 ]

        Avec grep j'ai toutes lignes contenant le mot or il faut que la ligne commence par ce mot

        2) Pour la récursivité c'est bien ici que je dois le faire avec : $0 $i ?

        echo "STOP"

        3) Après j'ai toujours le problème pour récupérer $DEPENDANCES et $COMMANDE selon la cible :
        Si la cible est toto je dois pouvoir mettre dans

        $DEPENDANCES= toto.o

        $COMMANDE= touch toto
        echo toto est touche

        Dans ce script cela fonctionne que quand il n'y a qu'un seul bloc dans le makefile :

        toto: toto.o
        touch toto
        echo toto est touche

        Quand il y a plusieurs blocs je n'arrive pas a récupérer juste le bloc correspondant le nom de la cible

        Voila merci d'avance

        • [^] # Re: Récursivité

          Posté par  . Évalué à 2.

          Je crois que tu devrais répondre aux questions que l'on t'a poséess :
          - as-tu vu la notion de fonction shell dans ton cours ? Si tu ne réponds pas à ça nous pourrions te donner une mauvaise piste.
          - a quoi sert head ?

          Autre chose tu n'as pas tenu compte de toutes les remarques : UUOC et remplacement de deux sed par un seul (on peut mettre un ';' pour inclure plusieurs motifs de remplacement dans un sed).

          • [^] # Re: Récursivité

            Posté par  . Évalué à 1.

            • Oui nous avons vu la notion de fonction shell

            • head permet d'afficher le début d'un fichier, dans mon code head -1 la première ligne

            Et la correction :

            #!/bin/sh
            if [ ! -e $1 ]
            then
                DEPENDANCES=` grep -v '^#' makefiletest | grep "$1" | sed 's/\t//g' | cut -d ':' -f2 | head -1`
                COMMANDE=`grep -v '^#' makefiletest | grep -v ':' | sed 's/\t//g;s/ /:/g'`
            
                for i in $DEPENDANCES
                do
                    if [ -e $i ]
                    then for k in $COMMANDE
                    do
                        var=`echo $k | sed 's/:/ /g'`
                        sh -c "$var"
                    done
                    else
                        grep $i makefiletest 2>&1 /dev/null
                        if [ $? -ne 0 ]
                        then
                            echo "prérequis $i inexistant"
                            exit 1
                        else
                            echo "STOP"
                            exit 0
                        fi
                    fi
                done
            else
            echo "La cible $1 existe deja"
            exit 0
            fi

            J'en suis au même stade pour mes questions précédentes

            • [^] # Re: Récursivité

              Posté par  . Évalué à 2.

              Oui nous avons vu la notion de fonction shell

              sauf que dans ton exemple de code tu n'en utilises pas,
              et que la fonction() c'est la base de la recursité

              • [^] # Re: Récursivité

                Posté par  . Évalué à 1.

                Nous avons fait beaucoup de script utilisant la récursivité sans l'utilisation des fonctions, donc est-ce indispensable dans mon cas ?

                • [^] # Re: Récursivité

                  Posté par  . Évalué à 2. Dernière modification le 07 décembre 2014 à 15:33.

                  non, ce n'est pas indispensable,

                  mais dans ce cas là il faut que ton code soit recursif et qu'il s'appelle lui meme a un moment ou un autre (cf la definition de la recurisivité),
                  ce qui ne semble pas le cas dans ton code actuel

                  de plus l'enoncé te demande d'utiliser uniquement :

                  • find -newer …
                  • sh -c $CMD
                  • grep et sed

                  et dans ton code, y a du cat, head, cut

                  • [^] # Re: Récursivité

                    Posté par  . Évalué à 1.

                    Oui je n'ai pas encore mis en place la récursivité car j'ai déjà un problème avant voir 1) 3) de mon message précédent

                    Et j'ai enlever les "cat" dans la correction de mon code voir aussi dans le commentaire précédent sinon pour le "cut" je ne vois pas comment faire autrement c'est pour cela que je l'ai mis.

                    • [^] # Re: Récursivité

                      Posté par  . Évalué à 2.

                      ta recursivité doit demarrer des que tu as calculé les dependances et qu'il te faut voir si elles existent deja ou s'il faut les compiler.

                      en effet, faire compiler la cible, ou une dependance, ca doit etre la meme "fonction"
                      car dans les deux cas c'est :

                      • rechercher la cible X
                      • regarder les dependances de X
                      • calculer des dependances de X qui n'existent pas encore
                      • [^] # Re: Récursivité

                        Posté par  . Évalué à 1.

                        J'ai compris cela mais disons par exemple :

                        ./mon_script toto

                        D'après mon script plus haut :

                        Dans $DEPENDANCES -> je veux avoir 'toto.o'
                        Dans $COMMANDE -> je veux 'touch toto echo toto est touche'

                        Après je vérifie les dépendances :

                        Si toto.o existe
                        J’exécute tout ce qu'on trouve dans $COMMANDE
                        Sinon ( récursivité ) je relance mon script avec comme argument toto.o ( ce qu'on trouve dans $DEPENDANCES )

                        ==========================================================================================================================================================================================================================================================================================================================================================================

                        Donc le script aura maintenant
                        $DEPENDANCES -> toto.c
                        $COMMANDE -> touch toto.o echo toto.o est touche

                        Et on refait les tests .. et ainsi de suite

                        Mon problème ici est que je n'arrive pas à stocker dans COMMANDE ET DEPENDANCES les lignes nécessaires.

                        • [^] # Re: Récursivité

                          Posté par  . Évalué à 1. Dernière modification le 07 décembre 2014 à 17:09.

                          Salut,

                          Mon problème ici est que je n'arrive pas à stocker dans COMMANDE ET DEPENDANCES les lignes nécessaires.

                          Commence déjà par traiter le problème des dépendances et la récursivité. La partie commande pourra être résolue dans un second temps.

                          Sans la récursivité, on ne va pas y arriver à t'aider. Donc met ça en place :)

                          Edit : Ah et aussi, dans l'énoncé, il est dit qu'il n'y a qu'une seule dépendance. Donc inutile de penser trop générique.

                          Matricule 23415

                        • [^] # Re: Récursivité

                          Posté par  . Évalué à 2.

                          le cours porte sur la recursivité, ce qui est important c'est donc le travail sur les dependances et le fait de depiler recursivement celles-ci.

                          tu peux reflechir à plusieurs techniques, mais globalement regarde ton fichier tu y verras un motif

                          A:D1
                          C1
                          C2
                          #Commentaire avec une ligne vide en dessous
                          
                          D1:D2
                          C1
                          C2

                          focalise toi sur le fait de trouver ta cible, et sa dependance,
                          puis verifier si la dependance a elle meme une dependance, etc

                          recuperer les commandes se fera en modifiant simplement ta fonction de recherche de la cible
                          si la cible n'existe pas, mais que la dependance existe, alors il faut lancer les commandes.

                          • [^] # Re: Récursivité

                            Posté par  . Évalué à 1.

                            En fait j'ai écrit le script avec la récursivité mais je ne sais pas s'il fonctionne et pour vérifier je dois récupérer correctement $DEPENDANCES / $COMMANDE :

                            #!/bin/sh
                            
                            FAUX -> DEPENDANCES=` grep -v '^#' makefile | grep "$1:" | sed 's/\t//g' | cut -d ':' -f2 | head -1 `
                            FAUX -> COMMANDE=`grep -v '^#' makefile | head -4 | tail -2 | sed 's/\t//g;s/ /:/g'`
                            
                            #echo $DEPENDANCES
                            #echo $COMMANDE
                            
                            if [ ! -e $1 ]
                            then
                                if [ ! -e $DEPENDANCES ]
                                then
                                    $0 $DEPENDANCES
                                else
                                    for k in $COMMANDE
                                    do
                                        var=`echo $k | sed 's/:/ /g'`
                                        echo $var
                                        sh -c "$var"
                                    done
                                    $0 toto
                                fi
                            else
                            echo "$1 existe déjà"

                            Donc je cherche toujours le moyen de trouver pour "greper" correctement ce qu'il me faut :

                            • $DEPENDANCES : grep 'toto:' makefile | cut -d ':' -f2 | sed 's/\t//g'

                            Ça marche mais pour
                            grep 'toto.o:' makefile | cut -d ':' -f2 | sed 's/\t//g'
                            J'obtiens les résultats pour deux cibles ( toto.o et totooo )
                            Comment je désactive le . en tant que caractère générique

                            • $COMMANDE : Ici j'essaye de récupérer les lignes après le $DEPENDANCES jusqu’à qu'il y ai une ligne vide
                            LIGNE=`sed -n "/$1:/=" makefile`
                            TEXTE=`sed -n "$LIGNE p" makefile`
                            
                                while [ -z $TEXTE ]
                                do
                                    LIGNE=`expr $LIGNE + 1`
                                    TEXTE=`sed -n "$LIGNE p" makefile`
                                    echo $TEXTE
                                done

                            Je ne sais pas pourquoi mais ça ne fonctionne pas lorsque je lance ce petit script ( message d'erreur -> [: 13: toto:: unexpected operator )

                            Voila merci d'avance

                            • [^] # Re: Récursivité

                              Posté par  . Évalué à 2.

                              comme dit precedemment ne te focalise pas sur la recuperation des commandes, ce n'est pas le sujet de l'exercice.

                              le but c'est de savoir faire de la recursivité.
                              si ton fichier contient 4 cibles, A/B/C/D avec un enchainement de dependance A->B->C->D,
                              ton code doit pouvoir faire au minimum les choses suivantes en partant d'un make A

                              cherche le motif 'A:' pour trouver `A:B`
                              recupere la valeur B
                              
                              # à partir de là ca doit se faire en automatique grace à la recursivité
                              chercher le motif B: pour trouver B:C
                              recupere la valeur C
                              
                              puis recommence, cherche le motif C: pour trouver C:D
                              recupere la valeur D
                              # ici ce termine la recursivité

                              une fois que tu sais faire ca,
                              travaille la fonction qui recupere la valeur,
                              tu pourras surement y ajouter de quoi recuperer les lignes qui sont apres le motif A:B comme etant les commandes a executer si la cible A n'existe pas.

                              • [^] # Re: Récursivité

                                Posté par  . Évalué à 1.

                                Donc ce script ne fait pas ce que tu demande ? :

                                if [ ! -e A ]
                                then
                                    if [ ! -e B ]
                                    then
                                        $0 $B
                                    else
                                        for k in $COMMANDE
                                        do
                                            var=`echo $k | sed 's/:/ /g'`
                                            echo $var
                                            sh -c "$var"
                                        done
                                        $0 A
                                    fi
                                else
                                echo "$1 existe déjà"
                                • [^] # Re: Récursivité

                                  Posté par  . Évalué à 1.

                                  Salut,

                                  Donc ce script ne fait pas ce que tu demande ?

                                  Pas du tout :)

                                  Par contre, on voit l'introduction de $0 et ça, c'est plutôt bien.

                                  On part sur une bonne piste là.

                                  Matricule 23415

                                  • [^] # Re: Récursivité

                                    Posté par  . Évalué à 1.

                                    Je dois rendre le travail demain donc si vous pourriez me guider un peu plus, ça fait deux jours que je suis dessus

                                    #!/bin/sh
                                    
                                    # $1 c'est la cible donc A
                                    B=`grep '$1:' | sed 's/$1://g;s/\t//g'`
                                    # J'ai "greper" le motif A: et j'en recupere la valeur B
                                    
                                    for k in $B
                                    do
                                        $0 $B
                                    done
                                    
                                    # Je relance le script avec la récursivité pour qu'il cherche le motif B et récupère C ( etc ... )

                                    C'est avec cette base que je dois faire mon script ? C'est bon pour la récursivité la ?

                                    • [^] # Re: Récursivité

                                      Posté par  . Évalué à 2.

                                      Je dois rendre le travail demain donc si vous pourriez me guider un peu plus, ça fait deux jours que je suis dessus

                                      et depuis 2 jours tu n'es pas allé relire le cours sur la recusivité, ce que cela implique comme demarche ?

                                      C'est avec cette base que je dois faire mon script ? C'est bon pour la récursivité la ?

                                      ca devrait,
                                      seulement tu fais une boucle avec comme variable k
                                      mais tu ne te sers pas de k dans l'execution qui suit.

  • # $1 != Makefile

    Posté par  . Évalué à 2.

    Si je comprends bien ton script, il prend comme argument le fichier Makefile.
    L'exercice dit « Votre commande admettra un argument, le nom de la cible à atteindre », donc pas le Makefile mais la cible ($APRES dans ton script)

    Personnellement, $DEPENDANCES et $CIBLE me parlent plus que $AVANT et $APRES.

  • # déjà

    Posté par  (site web personnel) . Évalué à 2. Dernière modification le 05 décembre 2014 à 19:47.

    cat $1 | grep -v '^#' euhhhhhhhhhh grep -v '^#' $1

    et ensuite j'ai lu rapide ton truc je ne sais pas du tout si c'est ce que tu veux faire.

    while read line; do
     (ton traitement par ligne)
    done < tonfichier
    

    et en remarque, c'est sous linux ? ton prof dit "sh" mais c'est du vrai "sh" historique ou du bash/dash/ksh …

    Is it a Bird? Is it a Plane?? No, it's Super Poil !!!

    • [^] # Re: déjà

      Posté par  . Évalué à 2.

      ya aussi sed 's/\t//g'| sed 's/ /:/g' qui est moche et peut être remplacé par un seul appel à sed.

  • # Qui dit exercice de cours, dit "LIRE et COMPRENDRE le cours avant de commencer"

    Posté par  . Évalué à 3.

    1°) la recursivité : cela implique que la fonction s'appelle elle-meme pour traiter un sous morceau d'un objet.
    par exemple dans un parcours d'un arbre, on appelle une fonction traite_feuille(noeud_courant) si le noeud en cours à des feuilles,
    et si la feuille suivante est en fait un noeud (c'est un test dans la fonction traite_feuille()), on appelera de nouveau cette fonction.

    2°) appliqué à ton probleme
    -- il faut detecter la presence d'un fichier makefile
    -- il faut chercher la cible ($1) dans ce fichier, et traiter les ordres qui sont dans les blocs en dessous (en utilisant la recursivité)

  • # Essai

    Posté par  . Évalué à 1.

    J'ai refait le script ( j'ai modifié le makefile car je ne sais pas distinguer le cas du toto.o et totooo) :
    http://img4.hostingpics.net/pics/798206popo.jpg

    #!/bin/sh
    
    ligne=`sed -n "/$1:/=" makefile`
    texte=`sed -n "$ligne p" makefile`
    
    while [ ! -z "$texte" ]
    do
        ligne=`expr $ligne + 1`
        texte=`sed -n "$ligne p" makefile`
        echo "$texte"
    done >> CMD
    
    COMMANDE=`sed 's/ /:/g' CMD`
    DEPENDANCES=`grep "$1:" makefile | cut -d ':' -f2`
    
    if [ ! -e $1 ] || [ $1 -ot $DEPENDANCES ]
    then
        if [ -z $DEPENDANCES ]
        then
            for k in $COMMANDE
            do
                var=`echo $k | sed 's/:/ /g'`
                sh -c "$var"
            done
            rm CMD
            exit 0
    
        else
            if [ ! -e $DEPENDANCES ]
            then
                TEST=`grep "$DEPENDANCES:" makefile`
                if [ -z $TEST ]
                then
                    touch impossible
                    $0 impossible
                else
                    $0 $DEPENDANCES
                fi
            else
                for k in $COMMANDE
                do
                var=`echo $k | sed 's/:/ /g'`
                sh -c "$var"
                done
                $0 toto
            fi
        fi
    else
        rm CMD
        exit 0
    
    fi

    Le script fonctionne pour le cas ou il prend comme argument clean.
    Si tota existe, toto est bien crée
    Sinon je tombe toujours dans le cas impossible

    Par contre si toto.c existe, le script ne construit pas tota puis toto mais tombe dans le cas impossible aussi ..

    • [^] # Re: Essai

      Posté par  . Évalué à 1.

      Hello,

      j'ai modifié le makefile car je ne sais pas distinguer le cas du toto.o et totooo

      Normal, le . est un caractère neutre pour sed. Ton prof l'a mis la exprès pour voir.

      Donc évidemment, tu tombe en plein dedans. Mais je ne pense pas que ça ferra une grosse part dans la notation.

      Si tota existe, toto est bien crée
      Sinon je tombe toujours dans le cas impossible

      Par contre si toto.c existe, le script ne construit pas tota puis toto mais tombe dans le cas impossible aussi ..

      Bin ouep, normal aussi.

      Et tu as l'air de t'obstiner à continuer de confondre cible et dépendances dans tes sed, plus on a reperdu l'appel récursif pourtant introduit avant…

      Au boulot avant que la correction ne tombe ;)

      Matricule 23415

    • [^] # Re: Essai

      Posté par  . Évalué à 2.

      comme dit kaos, tu ne sembles meme pas avoir compris la difference entre la cible, la dependance, les commandes.

      soit un makefile suivant :

      A:B
        commande1
        commande2
      
      B:C
        commande3
      
      C:
        commande4

      A est une cible
      dans A:B, B est une dependance

      dans B:C
      B est la cible, C est la dependance

      et dans C:
      C est la cible

      ensuite pourquoi tu essaies de rajouter des : dans tes commandes, pour ensuite executer chacun des elements separement (ta boucle sur k…)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.