Forum Programmation.shell lecture d'un fichier

Posté par  (site web personnel) .
Étiquettes : aucune
0
21
avr.
2005
Salut.

Je bloque sur un problème que je qualifierais de "à la noix".
Je dois lire un fichier, et extraire en des valeurs. Pour cela j'ai fait un truc du genre :

cat fichier | grep machin | while read ligne ; do
variable=$(echo $ligne | sed 's/truc//')
echo "dans la boucle variable == $variable"
done
echo "maintenant variable == $variable"


Bon c'est un peu plus compliqué que ça mais ça suffit pour comprendre le problème.
Evident d'ailleurs : ma boucle est dans un sous-shell, donc variable est bien affectée mais elle est inconnue à l'extérieur de la boucle :

dans la boucle variable == valeur
maintenant variable ==


La question est donc : comment faire pour récupérer la valeur de variable à l'extérieur de la boucle ?
  • # export

    Posté par  . Évalué à 1.

    mais bon je pense que tu devrais t'y prendre autrement
    déjà le

    cat fichier | grep machin

    on peut éviter un sous process par

    grep machin fichier

    mais je taperais un ptit coup de perl pour éviter le gloubiboulga...


    #!/usr/bin/perl -w
    # script: remptruc.pl
    while(<>){
    chomp;
    s/truc//;
    print "$_\n";
    }


    usage: remptruc.pl fichier
  • # Plus simple

    Posté par  (site web personnel) . Évalué à 2.

    Tu peux essayer:
    for i in `grep machin fichier`;do
    XYZ
    done
    Enfin ca marche si tes lignes n'ont pas d'espaces
  • # lecture d'un fichier

    Posté par  (site web personnel) . Évalué à 2.

    Bon tout d'abord, faut arrêter avec ce vieux truc qui traîne ! cat fichier | grep machin
    grep sait se débrouiller tout seul comme un grand : grep machin fichier ça fait tout pareil et ça retarde le syndrome du canal carpien* ;)

    Bon, je sais pas si c'est très bien optimisé, voici une solution :

    je_boucle=1
    # on récupère le echo $variable dans variable
    variable=$(grep machin | while ((je_boucle)); do
    read ligne
    # si la ligne est vide, on arrête la boucle et on affiche la valeur de variable
    if [ -z "$ligne" ]; then
    je_boucle=0
    echo $variable # variable == valeur
    else
    variable=$(echo $ligne | sed 's/truc//') # variable = valeur
    fi
    done)

    echo "maintenant variable == $variable" # ça écrit valeur



    * : http://www.algo.be/ergo/risques.htm(...)
  • # compléments d'explication

    Posté par  (site web personnel) . Évalué à 1.

    Bon désolé de ne pas avoir été clair dès le début, mais je ne voulais pas compliquer. Je vais donc expliquer plus en détail mon problème. Le fichier que je dois lire est un fichier de config qui ressemble à ça (il peut contenir des lignes vides) :
    # Serveur ou sera enregistree la sauvegarde
    serveur : monserveur.fr
    
    # Nom de connexion a utiliser sur le serveur
    usager : toto
    
    # Chemin abslou du repertoire ou sont enregistrees les sauvegardes sur le serveur
    chemin : /sauvegardes
    
    # Chemin abslou du repertoire ou sont enregistres les fichiers d'erreurs
    chemin_err : /sauvegardes/ERREURS
    
    # Identifiant du client :
    id : 1
    
    # Liste des fichiers a sauvegarder :
    sauv : /root
    sauv : /home/toto
    sauv : /etc
    
    Je dois récupérer toutes les options (serveur, usager...) et les enregistrer dans des variables. Mon script actuel ressemble à ça :
      # Lecture du fichier de configuration
    
      sed 's/ *\#.*//' fichier_config | egrep -v '^$' | while read ligne ; do    # Lecture du fichier de configuration (et suppression des commentaires).
        echo $ligne
    
        if echo $ligne | egrep '^[	 ]*sauv[	 ]*:[ 	]*.+$' >/dev/null ; then
          sauv=${sauv}\n$(echo $ligne | sed -n 's/^[	 ]*sauv[	 ]*:[ 	]*//p')
    
        elif echo $ligne | egrep '^[	 ]*serveur[	 ]*:[ 	]*.+$' >/dev/null ; then
          serveur=$(echo $ligne | sed 's/^[	 ]*serveur[	 ]*:[ 	]*//')
    
        elif echo $ligne | egrep '^[	 ]*usager[	 ]*:[ 	]*.+$' >/dev/null ; then
          usager=$(echo $ligne | sed 's/^[	 ]*usager[	 ]*:[ 	]*//')
    
        elif echo $ligne | egrep '^[	 ]*chemin[	 ]*:[ 	]*.+$' >/dev/null ; then
          chemin=$(echo $ligne | sed '{ s/^[	 ]*chemin[	 ]*:[ 	]*// ; s@/[ 	]*$@@ }')   # On supprime a la fois "chemin : " et le dernier / s'il existe.
    
        elif echo $ligne | egrep '^[	 ]*chemin_err[	 ]*:[ 	]*.+$' >/dev/null ; then
          chemin_err=$(echo $ligne | sed '{ s/^[	 ]*chemin_err[	 ]*:[ 	]*// ; s@/[ 	]*$@@ }')   # On supprime a la fois "chemin : " et le dernier / s'il existe.
    
        elif echo $ligne | egrep '^[	 ]*id[	 ]*:[ 	]*.+$' >/dev/null ; then
          id=$(echo $ligne | sed 's/^[	 ]*id[	 ]*:[ 	]*//')
        fi
      done
    
      # C'est là que ça coince :
    
      echo "serveur = $serveur"
      echo "usager = $usager"
      echo "fich_err = $fich_err"
      echo "id = $id"
      echo "chemin = $chemin"
      echo "chemin_err = $chemin_err"
      echo "dest = $dest"
      echo "sauv = $sauv"
    
    Donc j'ai plusieurs valeurs à récupérer dans la boucle, et avec vos solutions je ne vois pas comment faire. C'est peut-être faisable en perl mais je ne connais pas le perl... Voili voilou, merci de votre aide :-)
    • [^] # Re: compléments d'explication

      Posté par  (site web personnel) . Évalué à 2.

      Ah, je viens de retrouver une astuce ; cette astuce permet de ne pas utiliser de sous-shell, ainsi les valeurs des variables dans la boucle seront les même qu'à l'extérieur de la boucle :
      while read ligne; do
              variable=$(expression avec $ligne)
      done <<<"$(expression sed avec fichier_config)"
      explications: les « <<< » font en sorte que la chaîne d'après soit considéré comme si c'était un fichier, les guillemets autour de $(expression..) sont important car sans ça bash ignore les retours chariots et tu te retrouve un résultat qui tient tout sur une ligne ;)
      • [^] # Re: compléments d'explication

        Posté par  (site web personnel) . Évalué à 1.

        Merci beaucoup c'est exactement ce qu'il me fallait !

        A noter que cette astuce marche sous bash mais pas sous sh : "Syntax error: redirection unexpected".

        Je n'ai pas essayé d'autres interpréteurs.

Suivre le flux des commentaires

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