Forum Programmation.perl classer des documents markdown par niveau de titres

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
31
jan.
2021

Il peut être pratique à certaines occasions de trier des fichiers markdown (ou apparentés), selon leur titres / entêtes. Cela peut concerner un classement par dates, ou par numéros de chapitres par exemple, ce qui pourrait s'appliquer pour un blog, un livre etc

Un exemple de fichier de départ :

C'est un exemple pour le script de classement par titres.

# Chapitre 01

Cette partie appartient au "Chapitre 01".

## 2020-12-15  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-15.

## 2020-12-14  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-14.

## 2020-12-16  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-15.

# Chapitre 02 

Cette partie appartient au "Chapitre 02".

## 2020-11-17  

Cette partie appartient au "Chapitre 02", et a pour titre 2020-11-17.

## 2021-02-14  

Cette partie appartient au "Chapitre 02", et a pour titre 2021-02-14.

## 2020-12-16  

Cette partie appartient au "Chapitre 02", et a pour titre 2020-12-15.

# Chapitre 04 

## 2020-11-17  

Cette partie appartient au "Chapitre 04", et a pour titre 2020-11-17.

## 2020-10-07  

Cette partie appartient au "Chapitre 04", et a pour titre 2020-10-07.

# Chapitre 03

## 2020-11-17  

Cette partie appartient au "Chapitre 03", et a pour titre 2020-11-17.

## 2020-04-06  

Cette partie appartient au "Chapitre 03", et a pour titre 2020-04-06.

Idéalement, il devrait être possible de classer les titres 1 en premier, par ordre croissant, puis les sous titres (titre 2) également par ordre croissant, mais uniquement à l'intérieur de leur parent.

Ce qui donnerait cela :

C'est un exemple pour le script de classement par titres.

# Chapitre 01

Cette partie appartient au "Chapitre 01".

## 2020-12-14  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-14.

## 2020-12-15  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-15.

## 2020-12-16  

Cette partie appartient au "Chapitre 01", et a pour titre 2020-12-15.

# Chapitre 02 

Cette partie appartient au "Chapitre 02".

## 2020-11-17  

Cette partie appartient au "Chapitre 02", et a pour titre 2020-11-17.

## 2020-12-16  

Cette partie appartient au "Chapitre 02", et a pour titre 2020-12-15.

## 2021-02-14  

Cette partie appartient au "Chapitre 02", et a pour titre 2021-02-14.

# Chapitre 03

## 2020-04-06  

Cette partie appartient au "Chapitre 03", et a pour titre 2020-04-06.

## 2020-11-17  

Cette partie appartient au "Chapitre 03", et a pour titre 2020-11-17.

# Chapitre 04 

## 2020-10-07  

Cette partie appartient au "Chapitre 04", et a pour titre 2020-10-07.

## 2020-11-17  

Cette partie appartient au "Chapitre 04", et a pour titre 2020-11-17.

J'ai trouvé un petit script qui permet de faire ça, mais qui ne prend pas en compte toutes les possibilités :

https://stackoverflow.com/questions/25351917/sort-markdown-file-by-heading

perl -0777 -ne '
        (undef,@paragraphs) = split /^#(?=[^#])/m; 
        print map {"#$_"} sort @paragraphs;
    ' file.md

Le problème, c'est que si on classe par titre 1, la ou les lignes avant le titre 1 sont effacées.

Si on adapte pour classer par titre 2, avec ça à la place :

    perl -0777 -ne '(undef,@paragraphs) = split /^##(?=[^#])/m; print map {"##$_"} sort @paragraphs;' file.md

cela ne va bien évidemment pas prendre en compte les titres niveau 1, et donner un résultat non souhaité.

Avez-vous des idées pour corriger cela ? Je n'y connais pas grand chose en perl (ça peut aussi se résoudre en python ou autre… à votre bon coeur…)

  • # Premier niveau

    Posté par  . Évalué à 1.

    C'est le undef qui te supprime la première correspondance mais si tu l'enlève, ton premier paragraphe ne se retrouvera pas au bon endroit. Le plus simple pour trier sur le premier niveau de titre, c'est d'ajouter # Chapitre 00 au début du fichier et l'enlever par après.

    • [^] # Re: Premier niveau

      Posté par  . Évalué à 2.

      ok, mais le but c'était de ne pas modifier le document de départ, sinon c'est trop fastidieux…

      • [^] # Re: Premier niveau

        Posté par  . Évalué à 3. Dernière modification le 01/02/21 à 17:42.

        Ben non, désolé, ce n'est pas pratique, il suffisait de remplacer undef par une variable scalaire comme proposé en-dessous. Enfin, ça m'a donné envie de me remettre sérieusement au Perl.

  • # Non testé

    Posté par  (site Web personnel) . Évalué à 4.

    Dans sort.pl:

    local $/;
    my $text = <>;
    my ($start, @chapters) = split/^#(?=[^#])/m, $text;
    print $start;
    for (sort @chapters) {
        my ($intro, @subchapters) = split/^##(?=[^#])/m;
        print "#$intro";
        print map {"##$_"} sort @subchapters; 
    }

    Puis:

    $ perl sort.pl file.md
    
    • [^] # Re: Non testé

      Posté par  . Évalué à 3.

      super, merci beaucoup, ça fonctionne parfaitement, bien joué !

      Je n'y connais pas grand chose en perl, mais j'ai adapté le script pour rajouter également un troisième niveau, ce qui donne par exemple ça :

      #!/usr/bin/env perl
      
      local $/;
      my $text = <>;
      my ($start, @chapters) = split/^#(?=[^#])/m, $text;
      print $start;
      for (sort @chapters) {
          my ($intro, @subchapters) = split/^##(?=[^#])/m;
          print "#$intro";
              for (sort @subchapters) {
              my ($intro2, @subsubchapters) = split/^###(?=[^#])/m;
              print "##$intro2";
              print map {"###$_"} sort @subsubchapters; 
              }
      }

      on a également la version txt2tags (ou creole) en remplaçant les # par des =

      • [^] # Re: Non testé

        Posté par  (site Web personnel) . Évalué à 4.

        Je n'y connais pas grand chose en perl, mais j'ai adapté le script pour rajouter également un troisième niveau, ce qui donne par exemple ça :

        Et après y'en à qui disent que Perl est un langage imbuvable dont seul celui qui l'écrit est capable de le lire ! En tout cas bravo !

        « Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes. »

        • [^] # Re: Non testé

          Posté par  . Évalué à 4.

          Et après y'en à qui disent que Perl est un langage imbuvable dont seul celui qui l'écrit est capable de le lire ! En tout cas bravo !

          Je peux coder en mode WOL (Write Only Language) dans n'importe quel langage de programmation; perl de par ses variables automatiques et l'utilisation des RegEx peut aisément devenir difficile à comprendre, et c'est plus facile dans ce langages que dans pas mal d'autre;

          Mais le développeur peut tout à fait le coder parfaitement lisible, et donc maintenable; dès qu'on a besoin de manipuler du texte en fonction de RegEx, c'est même largement plus lisible que les autres langage tentant de faire la même chose.

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

Suivre le flux des commentaires

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