Forum Programmation.shell Cat et les espaces

Posté par  .
Étiquettes : aucune
0
7
août
2008
Bonjour à tous,

Je sais que cette question a déjà été traitée, mais je ne suis pas foutu de remettre la main sur les postes.

Je me casse tout le temps les dents sur l'utilisation de cat pour lire itérativement les lignes d'un fichier dans une boucle for.

Voici le dernier exemple en date :
echo "Aix en Provence;EcoledArt;24;27;true" | sed 's/^\([A-Z].*\);.*;.*;.*;true$/\1/'
va me renvoyer :
Aix en Provence
c'est ce que je cherche à obtenir, mais pour le contenu d'un fichier.
Une partie du fichier en question :
Marseille;SainteMarguerite;24;17;true
Marseille;CinqAvenues;23;19;true
Aubagne;PennesMirabeau;21;23;true
Aix en Provence;EcoledArt;24;27;true
Aix en Provence;LesPlatanes;25;28;true
Toulon;Arsenal;38;12;true
Toulon;LaValette;40;13;true
Hyeres;hyeres;43;13;true


la boucle que j'utilise :
for ligne in $(cat fichier_source );do echo ${ligne} | sed 's/^\([A-Z].*\);.*;.*;.*;true$/\1/'; done


et là, c'est le drame, parceque cat traite les bloques de caractères séparés par un espace et pas les lignes et je me retrouve avec :
Aix
en
Provence

Et je dois impérativement conserver mes espaces dans mes noms de stations.
Ce n'est qu'un exemple du problème récurant que je rencontre avec cat. Je suppose qu'il existe une "bonne pratique" pour contourner ce genre de problème.

Vos conseils m'aideraient beaucoup, je n'ai pas envie de passer à nouveau 2 plombes pour pondre un bout de script dégueu pour contourner le problème.

Merci à tous, et bonne soirée !

PS : le vrai bout de code dans lequel ça coince :
for ligne in $(cat ${fichier_source})
do
fichier_ville="$(echo $ligne | sed 's/^\([A-Z].*\);.*;.*;.*;true$/\1/')"
if [ ! -e ${chemin}/tmp/$fichier_ville ]
then
touch ${chemin}/tmp/$fichier_ville
fi
echo $ligne >> ${chemin}/tmp/$fichier_ville
done
  • # read

    Posté par  . Évalué à 4.

    cat tonfic | while read line
    do
    echo $line
    done
    • [^] # Re: read

      Posté par  . Évalué à 1.

      FAN-TAS-TIQUE !
      Merci pour la réponse rapide :)

      Bonne soirée
    • [^] # Re: read

      Posté par  . Évalué à 3.

      J'allais le dire :)

      Attention toutefois au comportement par défaut de read, qui comprend l'antislash comme le caractère d'échappement. Ainsi, dans le fichier donné à cat, si l'on a \X (X étant n'importe quel caractère autre que le retour à la ligne), l'antislash disparait on obtiend X. Et si X est un retour à la ligne, il est supprimé donc la ligne continue. Conclusion: mieux vaut donner à read l'option -r qui annule toutes ces modifications.

      Vive POSIX \o/
      • [^] # Re: read

        Posté par  . Évalué à 1.

        Je note, je note :)
  • # Le shell !

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

    ce n'est pas cat qui fait ça, mais ton shell quand il fait l'intégration sur le résultat du cat.
    Si tu utilises bash, tu devrais regarder du côté de la variable d'environnement IFS, man bash [1] est ton ami.

    [1] http://pwet.fr/man/linux/commandes/bash

    https://damien.pobel.fr

    • [^] # Re: Le shell !

      Posté par  . Évalué à 1.

      Merci, je me suis documenté sur IFS. Ca résout pas mal de mes problèmes !
  • # Useless use of cat...

    Posté par  . Évalué à 5.



    sed 's/^\([A-Z].*\);.*;.*;.*;true$/\1\000/' ${fichier_source} | while read fichier_ville

    if [ ! -e ${chemin}/tmp/$fichier_ville ]

    then

    touch "${chemin}/tmp/$fichier_ville"

    fi

    echo $ligne >> "${chemin}/tmp/$fichier_ville"

    done



    Mais sinon c'est quoi l'interêt du touch avant le append par le echo ? si le fichier n'existe pas, il est automatiquement créé...

    De plus je te conseille de mettre des " autour des noms de fichiers, s'il y a des espaces ça risque de coincer.
    • [^] # Re: Useless use of cat...

      Posté par  . Évalué à 2.

      oups, j'ai laissé un \000 trainé dans la regexp, c'est un reste d'une idée à la con, à retirer, oeuf corse.
    • [^] # Re: Useless use of cat...

      Posté par  . Évalué à 2.

      Maintenant que tu le fais remarquer, absolument aucun intérêt. J'avais complètement zappé que le ">>" allait créer le fichier s'il n'existait pas.

      Heureusement que je ne vous ai pas mis l'intégralité du truc, c'est vraiment le script de la honte ! Quoique, j'aurais surement appris des tonnes de choses... :D
  • # Useless use of sed

    Posté par  . Évalué à 6.

    awk -F ";" '{print $1}'

    Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.

    • [^] # Re: Useless use of sed

      Posté par  . Évalué à 0.

      Il faut que j'apprenne awk. Je le rajoute en bas de la liste.
      Merci pour la commande beaucoup plus concise.
    • [^] # Commentaire supprimé

      Posté par  . Évalué à 2.

      Ce commentaire a été supprimé par l’équipe de modération.

      • [^] # Re: Useless use of sed

        Posté par  . Évalué à 2.

        Oui, mais non, parce que j'ai pas mis le test sur le "true" dans le cinquième champs, mais qu'on peut le faire en awk mais pas avec cut (enfin, moi je ne sais pas le faire avec cut en tout cas)

        Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 1.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: Useless use of sed

            Posté par  . Évalué à 3.

            awk -F";" '/true$/ {print $1;}'

            Ca permet de ne lancer qu'une commande au lieu de 2.

            Etienne
            • [^] # Re: Useless use of sed

              Posté par  . Évalué à 2.


              Il peut être parfois plus rapide d'apprendre un seul langage que 36 syntaxes de différents utilitaires dés lors que la tache est un minimum complexe.


              Par ex en Perl l'exercice précédent se simplifie en :


              perl -pe 'open STDOUT,">>",(split /;/)[0]' ${fichier_source}


              ;-)
            • [^] # Commentaire supprimé

              Posté par  . Évalué à 1.

              Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: Useless use of sed

            Posté par  . Évalué à 2.

            Mauvaise habitude ...

            Il vaut mieux faire un awk ou un perl bien senti que des grep | cut |head | sed, surtout lorsque l'on traite de grosses quantités de données. Un perl ( ou awk) est évalué au lancement de la commande et après il traite massiveme
            nt les données, une ligne avec plein de | dans une boucle shell est évaluée à chaque occurence de la boucle.

            Donc après faut voir ce que l'on cherche ... une cpmmande jetable qui traite une dizaine de ligne : ca serrt à rien de se prendre la tete, pour un fichier de plusieurs millions de lignes, il vaut mieux se poser la question.
            • [^] # Commentaire supprimé

              Posté par  . Évalué à 1.

              Ce commentaire a été supprimé par l’équipe de modération.

              • [^] # Re: Useless use of sed

                Posté par  . Évalué à 1.

                J'ai déjà traité des millions de lignes en script bash à coup de grep, cut et autres. Je ne suis pas sur que, dans certains cas, perl/python (ou tout langage interprétés) auraient fait mieux. Cela n'était pas nécessairement du jetable mais des jobs batches qui pouvaient prendre toute la nuit si nécessaire.


                Je l'ai déjà fait aussi et je te garantis que la différence est nette. C'etait pour un truc du genre :

                while read a b c .....
                do
                var=echo a | grep (ou cut ou sed je me rappelle plus)
                plusieurs lignes du même genre ....

                done.

                Tu imbriques ca dans une ou deux boucles et typiquement tu te retrouve avec un truc qui met des plombes a s'exécuter.
            • [^] # Re: Useless use of sed

              Posté par  . Évalué à 1.

              Il vaut mieux faire un awk ou un perl bien senti que des grep | cut |head | sed, surtout lorsque l'on traite de grosses quantités de données.

              L'avantage d'utiliser plusieurs commandes du genre grep | cut |head | sed est qu'elles vont s'exécuter en parallèle et tirer ainsi partie des multicoeurs des processeurs actuels alors qu'un script perl ne tournera que sur un seul coeur.
              • [^] # Re: Useless use of sed

                Posté par  . Évalué à 2.

                L'avantage d'utiliser plusieurs commandes du genre grep | cut |head | sed est qu'elles vont s'exécuter en parallèle et tirer ainsi partie des multicoeurs des processeurs actuels

                oui sauf que ... il vaut mieux un awk plutot qu'un while read + serie de echo | sed| grep .... La différence est nette, même sur systeme multi-coeur.

Suivre le flux des commentaires

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