Forum Programmation.shell Tri de fichiers et expressions rationnelles

Posté par  .
Étiquettes : aucune
0
24
août
2005
Bonjour à tous.

Je suis en train d'écrire un script en Bash qui traite des fichiers.
2 problèmes se posent à moi:

>> premièrement, parmi les fichiers se trouvant dans un répertoire, je dois extraire le nom du dernier fichier dans l'ordre alphabétique croissant. Je crois qu'il faut se servir de ls, mais je n'y suis pas arrivé. Enfin, je suis tombé sur la commande
ls | cut -f 1 | tail -1
, mais c'est un peu du bricolage et je ne la comprends pas trop. Si vous aviez une solution plus élégante...

>> deuxièmement, il est question d'expressions rationnelles. Les fichiers à traiter ont un nom de ce type :

[chaîne de caractères][3 chiffres].extension

exemple : linux012.org
blablabla123.rpm

La chaîne de caractères comporte un nombre n de caractères, et uniquement des lettres.
Je voudrais enlever la chaîne de caractères et l'extension du nom des fichiers, pour extraire uniquement les chiffres. En clair, avec linux012.org, j'obtiendrai 012.
Je sais comment faire pour retirer l'extension. C'est la chaîne de caractères qui me pose problème. Je crois qu'il faut faire un truc du genre $(nom_fichier#*[a-z]}, mais ça n'enlève que la première lettre.

>> bonus: comment fait-on pour extraire plusieurs motifs en une seule ligne?
Exemple, j'ai un fichier nprénom.doc. Comment faire pour obtenir prénom sans faire

fichier=nprénom.doc
a=${fichier%.*}

puis

prénom=${a#[a-z]}

mais en une seule ligne?

Merci bien pour vos réponses.
  • # Le dernier fichier....

    Posté par  . Évalué à 3.

    Hello !
    Je n'ai pas toutes les solutions, mais j'en ai une. Mais d'abord quelques explications :
    ls | cut -f 1 | tail -1
    Fait un ls, en redirige la sortie vers la commande cut qui ne récupère que le premier champ, et enfin, redirige à nouveau la sortie vers la commande tail -1, qui ne conserve que la dernière ligne.
    Voilà pour les explications. Evidement, d'après ce que tu demandes, ça ne répond pas à ta question totalement.
    Tu peux faire ça :
    ls -c1 qui liste les fichiers sur une colonne. Ca permet de se passer du cut de ta commande. Rediriger tout ça vers un sort pour faire un tri. Puis rediriger vers un tail pour n'obtenir que la dernière ligne. Ce qui s'écrit :
    ls -c1 | sort | tail -1
    Tu peux aussi le faire à l'envers :
    ls -c1 | sort -r | head -1
    Enfin, si tu ne veux pas tenir compte de la casse (que 'a' soit triée de la même façon que 'A'), tu peux à cet effet utiliser l'option -f de sort.
    Au final, on obtient :
    ls -c1 | sort -f | tail -1 ou ls -c1 | sort -f -r | head -1
    Voilà. Je n'ai pas trouvé d'options à sort pour trier sur le nom de fichier, mais j'ai regardé rapidement. Tu peux te référer aux pages d'aide des différentes commandes. En voici déjà une ou deux :
    Page d'aide de sort : http://www.tu-berlin.de/zrz/dienste/www/manpages/sort.html(...)
    Page d'aide de ls : http://www.tu-berlin.de/zrz/dienste/www/manpages/ls.html(...)
    Page d'aide de head :
    http://www.tu-berlin.de/zrz/dienste/www/manpages/head.html(...)
    Enfin, page d'aide de tail : http://www.tu-berlin.de/zrz/dienste/www/manpages/tail.html(...)
    En espérant que ça aide, comme on dit.
    • [^] # Re: Le dernier fichier....

      Posté par  . Évalué à 1.

      Merci bien pour ta réponse !
      Déjà la moitié de mon problème résolu. ça avance!
      • [^] # Re: Le dernier fichier....

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

        Pour ce qui est des expressions régulières, tu peux faire appel à sed :
        echo toto123.lst | sed 's/[a-Z]*\([0-9]*\)\..*/\1/g'

        Avec en explication de texte pour l'expression réguliére :
        [a-Z]* : représente une suite de lettre de longueur 0 à +oo.
        \([0-9]*\) : mémorise une séquence de chiffre se de longueur 0 à +oo
        \. : représente un point tout con (le point à une signification)
        .* : représente n'importe quel suite de caractère de longueur 0 à +oo.

        Le résultat :
        [xxxx@xxxx ~]$ echo toto123.lst | sed 's/[a-Z]*\([0-9]*\)\..*/\1/g'
        123

        Tu balances ça dans un pipe après le ls et ça devrait te renvoyer tous les chiffres se trouvant derrière une suite de caractère.

        Pour l'extraction du contenu d'une chaîne de caractère, tu devrais être en mesure de faire les mêmes choses en changeant l'expression régulière.
  • # De l'utilisation fine des filtres unix

    Posté par  . Évalué à 3.

    Salut !

    J'espère que ma réponse te donnera entière satisfaction, pour les problèmes 1) et 2) j'ai fait des essais et en une ligne ça devrait coller.

    ls -1 | tail -1 | cut -d'.' -f1 | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z]//g'

    Donc dans l'ordre

    - le 'ls -1' affiche dans l'ordre alphabétique croissant
    - le tail prend la dernière ligne
    - le cut enlève l'extension (à condition qu'il n'y ait pas de points dans les autres chaînes de caractères)
    - le tr met tout en minuscule pour faciliter l'expression régulière avec sed.
    - le sed enlève tout les caractères non numériques

    J'obtiens le résultat de '021' en partant de la chaîne toto021.txt

    J'espère t'avoit aidé efficacement :-)

    @+

    dabowl_75

  • # Les trois chiffres.

    Posté par  . Évalué à 4.

    Plusieurs solutions ont été proposées :
    $A="linux123.org"

    echo $A| sed 's/\([[:alpha:]]\{1,\}\)\([0-9]\{1,\}\).*/\2/'
    ou
    echo $A | cut -d '.' -f 1 | cut -d 'x' -f 2
    ou
    echo ${A//[^0-9]/}
    ou
    echo $A | sed -e 's/.*\([0-9]\{3\}\)\..*/\1/'
    ou
    echo $A|sed 's/[^0-9]*\([0-9][0-9][0-9]\)\..*/\1/'

    Je ne vais pas en citer ici tous les auteurs de ces solutions.
    Teste-les, et garde celle qui te plait le mieux.

Suivre le flux des commentaires

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