Forum Programmation.shell Expression rationnelle - Majuscule/Miniscule

Posté par  .
Étiquettes : aucune
0
10
oct.
2005
Bonsoir,

Voilà, je me met un peu au script.
Je voudrais que de mon expression, l'élément "pattern" represente autant les mots majuscules que minuscules.
ex:
renommage par lot d'un nombre de fichier de même extensions mais dont la casse est différentes.
Je sais qu'il faut jouer avec ce genre d'elements [a-z][A-Z]
pourriez vous présenter 1 ou 2 exemples, genre une conversion complète et une autre ciblée.

En fait, rendre l'expression insensible à la casse pourrait être aussi une voie.

merci
  • # jette un oeil a man rename

    Posté par  . Évalué à 1.

    si ce que tu cherches a faire est simplement modifier les extensions d'un lot de fichiers, je te conseille qqch comme:

    rename 's/(.*)\.mp3/$1\.ogg/' *.mp3

    sinon, matcher les caracteres se ferait plutot avec [a-Z] mais pour un seul caractere... les expr reg bash ne sont pas tres évoluées et en général, lorsque l'on souhaite faire plus, on utilise egrep pour matcher, sed ou perl en ligne de commande pour les substitutions etc...
    • [^] # Re: jette un oeil a man rename

      Posté par  . Évalué à 1.

      ben en fait, il n'y aura pas que le renommage, j'aimerais inclure des boucles pour copier ou effacer.

      Donc rename, ça n'est peut-être pas bon.

      for i in *.motif <-- que "motif"² soit insensible à la casse par exemple

      une ptite illustration
      --------------------------

      for i in *.motif;
      if fonction expression
      if une condition
      do fonction $i expression; done
      else
      do fonction $i expression; done
      &&
      rm *.motif (où motif serait insensible à la casse)

      mais j'suis super ouvert, si vous faites intervenir sed ou egrep et le rendre plus interactif, genre pendant l'execution du script je peux changer la variable contenant le motif, je j'suis preneur. =)

      euh... oué bon, j'en demande trop,
      si vous pouviez déjà résoudre mon soucis de casse, j'vous en serais super gré! :)

      merci

      @+


      ²j'ai retrouvé le terme en français :)
      • [^] # options bash

        Posté par  . Évalué à 3.

        tu ne peux pas definir d'ER correcte pour ce que tu veux faire en shell bash ( en tout cas pour ce que j'en sais ), mais une solution éventuelle est de modifier le comportement du pattern matching du shell:

        encadre ton code par:

        shopt -s nocaseglob

        code

        shopt -u nocaseglob


        ceci permet des developpement non sensibles a la casse
        ( man bash pour les details )
        • [^] # Re: options bash

          Posté par  . Évalué à 1.

          Si tu as une version tcsh je suis preneur

          Pour l'option Bash, je ne voudrais pas changer le comportement du shell même pendant l'exec d'un script, donc si y a moyen de jouer juste avec le code, ça serait cool

          grand merci
    • [^] # Re: jette un oeil a man rename

      Posté par  . Évalué à 3.

      les expr reg bash ne sont pas tres évoluées
      Les patterns de base sont assez nazes, mais en bash-3.x y'a aussi le support des vraies regexps, même si elles sont pas forcement toujours très pratiques à utiliser (opérateur de comparaison "=~", et variable $BASH_REMATCH pour récupérer les matchs). En étant un peu tordu, enfin plus pour illustrer leur utilisation en fait, ça peut donnes des trucs dans ce genre là :
      for f in * ; do
      	if [[ "${f}" =~ '^([a-zA-Z]+)\.([mM][pP]3)$' ]] \
      	&& [[ "${BASH_REMATCH[2]}" != "mp3" ]] ; then
      		mv "${f}" "${BASH_REMATCH[1]}.mp3"
      	fi
      done
      Comme tu vois, je confronte des noms de fichier à une regexp 'achement compliquée, qui a deux sous expressions qui, quand ça matche, sont récupérables dans le tableau $BASH_REMATCH (et pour info, à l'indice 0 on aurait trouvé le match complet, ici équivalent à $f bien sûr). Heu, bon, on est bien d'accord que mon exemple est débile, mais bref, parfois c'est bien pratique pour éviter de forker des grep ou des sed...
      • [^] # Re: jette un oeil a man rename

        Posté par  . Évalué à 1.

        D'une certaine façon, plus j'augmente les indices, plus j'affine la correspondance?

        Bon c'est vrai que la regexp est touffu :) ça marche, mais ça sera pas evident d'en faire une version interactive.

        En tout cas, je te remerci, c'est instructif de voir une autre approche, aussi tordue soit-elle (ce sont tes mots :) ).


        . Heu, bon, on est bien d'accord que mon exemple est débile, mais bref, parfois c'est bien pratique pour éviter de forker des grep ou des sed...


        J'en suis pas encore à un soucis d'optimisation quoique, si j'vous ai posé la question c'est justement pour aller dans ce sens héhé.
        Bref, créer des forks ça m'dérange pas pour l'instant

        @+
        • [^] # Re: jette un oeil a man rename

          Posté par  . Évalué à 3.

          > D'une certaine façon, plus j'augmente les indices, plus j'affine la
          > correspondance?

          Mmh, pas tout à fait, enfin ça dépend ce que tu entends par là :)
          Disons que, après l'utilisation d'un "=~", le tableau BASH_REMATCH contient :
          - à l'indice 0, la chaine qui a matché l'ensemble de la regexp. Ici, c'est le nom de fichier ($f) complet, puisque ma regexp va obligatoirement du début jusqu'à la fin de la chaine ('^' au début et '$' à la fin). Mais si j'avais fait par exemple [[ "123plop.MP3" =~ '([a-ZA-Z]+)\.([mM][pP]3)' ]], on aurait eu BASH_REMATCH[0] qui vaudrait "plop.MP3", puisque le "123" lui n'est pas dans le match.
          - aux indices >= 1, le tableau contient les sous-expressions marquées entre parenthèses dans la regexp. Ça permet de récupérer des morceau de chaines. Ici, BASH_REMATCH[1] correspond au groupe "([a-ZA-Z]+)", donc au nom du fichier (note que c'est pas une bonne regexp pour un nom de fichier, vu que tu as en fait probablement des espaces ou des trucs du genre). Et BASH_REMATCH[2] correspond au groupe "([mM][pP]3)", donc à l'extension. Et au delà de 2, il n'y aura rien puisqu'il n'y avait que 2 groupes.

          > J'en suis pas encore à un soucis d'optimisation

          Ouais, là je me doute un peu que tu n'as pas 10000 fichiers à renommer d'un coup, et que donc tu t'en fiches. Mais c'est clair qu'il est utile de connaitre quelques bashismes pour éviter les forks quand on fait des grosses boucles, sinon on arrive vite à des scripts qui passent de quelques dixièmes de secondes à quelques minutes en temps d'exécution. C'est des bonnes habitudes à prendre.
          Par exemple, sans parler même du =~ qui est encore un peu trop récent pour pouvoir être largement utilisé, prends par exemple les substitutions "simples" dans les chaines... Tu vois souvent des crougnes de ce genre là :

          find . -type f -name '*.MP3' \
          | while read f ; do
          mv "${f}" "`echo $f | sed 's/\.MP3$/.mp3/'`"
          done

          Bon, bah c'est affreusement lent (on crée, pour chaque nom de fichier, un premier sous-shell pour le `...`, puis deux autres processus pour les 2 côtés du pipe). Alors qu'on peut écrire sans fork inutile dans la boucle :

          find . -type f -name '*.MP3' \
          | while read f ; do
          mv "${f}" "${f%.MP3}.mp3"
          done

          Enfin voilà, ça c'est déjà un exemple plus réaliste d'un truc où un petit bashisme permet de faire bien mieux que du bourne shell de base.
          • [^] # Re: jette un oeil a man rename

            Posté par  . Évalué à 1.

            Oui tu as bien compris, evidemment, si j'augmente l'indice j'dois aussi faire que le motif corresponde. j'vais pas faire un indice de 4 si il n'y a que 3 elements dans ma cible.;)
            En tout cas, j'avais pas du tout pensé à utiliser un tableau.

            Je posterai mon scripte une fois fini... ou si il y a des soucis -__^

            grand merci 'tgl'

Suivre le flux des commentaires

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