Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1491 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  [résolu] regex : extraire entre une paire d'accolades matchées

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[résolu] regex : extraire entre une paire d'accolades matchées

n°2106851
Argawaen
Posté le 18-10-2011 à 07:51:16  profilanswer
 

Bonjour
Je travaille en latex, j'ai un fichier .tex dans lequel j'aimerais supprimer toutes les occurences d'une certaine commande (avec un argument) que j'ai créé en la remplaçant par son argument.
Concrètement la commande est :
\newcommand{\corr}[1]{\textbf{#1}}
Elle m'a servi à mettre en gras certaines parties du texte (pour les corriger plus tard) tout en les différenciant dans le .tex des parties qui doivent rester en gras dans le doc final.
 
je pensais m'en sortir avec du Perl pour nettoyer tout ça...
Mais problème : l'argument peut contenir n'importe quel type de caractères y compris des paires d'accolades {} donc je n'arrive pas à le faire continuer jusqu'à la "}" qui matche la première "{" suivant "\corr".
 
Un exemple :
S'il rencontre la chaine "ceci est un exemple \corr{à corriger mais \textbf{cela} doit rester en gras}" je veux qu'il me donne "ceci est un exemple à corriger mais \textbf{cela} doit rester en gras".
 
 
Merci d'avance !
 
(en attendant j'ai surement plus vite fait de les enlever tous à la main dans mon fichier mais cette solution pourrait me reservir plus tard!)
 
 
Edit : en fait mon problème vient plutot de la situation quand il y a plusieurs occurences de cette même chaîne, j'arrive pas à les prendre une à une  :sweat:


Message édité par Argawaen le 18-10-2011 à 14:19:02

---------------
« Before we work on artificial intelligence why don’t we do something about natural stupidity? » Steve Polyak
mood
Publicité
Posté le 18-10-2011 à 07:51:16  profilanswer
 

n°2106926
gilou
Modérateur
Modzilla
Posté le 18-10-2011 à 13:43:57  profilanswer
 

Déjà, tu peux faire un \renewcommand{\corr}[1]{#1} en LaTeX pour ne plus être embêté par ta commande, non?
Pour le reste, je vais voir s'il y a une solution simple en Perl, mais j'en doute un peu, les trucs équilibrés dans les regexp, c'est pas si simple.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2106940
Argawaen
Posté le 18-10-2011 à 14:09:23  profilanswer
 

tout à fait en ce qui concerne l'allure du pdf  
mais comme ce .tex va être amené à circuler auprès de collaborateurs et uploadé sur le net (arxiv), je préfère autant qu'il soit "propre" et qu'on voit pas toutes les bidouilles internes.
 
En tout cas, en fouillant la doc de perlre (http://perldoc.perl.org/perlre.html#Capture-groups) j'ai fini par trouver le morceau de code magique :
 
my $re = qr{ ( \\corr ( \{ ( (?: (?> [^{}]+ ) | (?2) )* ) \} ) ) }x;    
s/$re/$3/;
 
j'ai mis tout ça dans une boucle while qui parcourt mon fichier, quelques conditions et c'est impec!!
2 lignes... Perl superior  :jap:
 

Spoiler :

   
La regex déployée et commentée :
$re = qr{ ( # paren group 1 (full function)
    foo
    ( # paren group 2 (parens)
    \(
    ( # paren group 3 (contents of parens)
    (?:
    (?> [^()]+ ) # Non-parens without backtracking
    |
    (?2) # Recurse to start of paren group 2
    )*
    )
    \)
    )
    )
    }x;
:D


Message édité par Argawaen le 18-10-2011 à 14:11:08

---------------
« Before we work on artificial intelligence why don’t we do something about natural stupidity? » Steve Polyak
n°2106957
gilou
Modérateur
Modzilla
Posté le 18-10-2011 à 15:12:55  profilanswer
 

Oui, ça marche bien:

Code :
  1. #!/usr/local/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $_ = 'ceci est un \textbf{exemple \corr{a corriger \corr{mais \textbf{ce\corr{la}} doit rester} en gras} fin de} l exemple';
  6. do 1 while (s/(\\corr(\{((?:(?>[^{}]+)|(?2))*)\}))/$3/g);
  7. print "$_\n";

note le $3 plutôt que \3 à la sed dans l'expression de substitution.

C:\Perl>perl balmatch.pl
ceci est un \textbf{exemple a corriger mais \textbf{cela} doit rester en gras fin de} l exemple


 
Je regardais du coté du module Text::Balanced, mais sa doc est loin d'être claire.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2107090
gilou
Modérateur
Modzilla
Posté le 19-10-2011 à 02:51:47  profilanswer
 

Noter aussi que la présence d'un { ou } escapé (\{ ou \}) fait foirer l'expression régulière.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2454173
dhenin
Posté le 12-09-2023 à 17:15:03  profilanswer
 

Bonjour je bloque sur un problème très proche : Avez-vous expérimenté Text::Balanced ?  
            $file_contents = <$file>;
            # Tableaux pour stocker les commandes \newcommand et \tikzset
            @newcommands = ();
            @tikzsets = ();
# Premier balayage pour extraire les commandes \newcommand et \tikzset
            # while ($file_contents =~ m/(?:\\newcommand|\\renewcommand)\\[^{}]*\{(?:[^{}]+|(.*))*\}|\\tikzset\{[^{}]+\}/sg)  {
            # do 1 while (s/(\\corr(\{((?:(?>[^{}]+)|(?2))*)\}))/$3/g);
            # while ($file_contents =~ m/(?:\\newcommand|\\renewcommand)\\[^{}]*\{(?:(?>[^{}]+)*)\}|\\tikzset\{[^{}]+\}/sg)  {
      while ($file_contents =~ m/(?:\\newcommand|\\renewcommand)\\[^{}]*\{(?:(?>[^{}]+)*)\}/sg)  {
                $content = $&;
print $content ;  
 
                if ($content =~ /newcommand/) {
                    push @newcommands, $content ;
 print "\n -----------   commande -------- \n" . $content ;  
                }
                elsif ($content =~ /tikzset/) {
                    push @tikzsets, $content ;
# print "\n -----------   Tikzset -------- \n" . $content ;  
                }
            }
Merci d'avance pour le coup de pouce  
 

n°2454259
rufo
Pas me confondre avec Lycos!
Posté le 13-09-2023 à 17:37:21  profilanswer
 

Merci de créer un nouveau topic dédié à ton pb plutôt que déterrer un vieux topic.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2454270
rat de com​bat
attention rongeur méchant!
Posté le 14-09-2023 à 00:29:30  profilanswer
 

et de mettre le code entre balises et d'expliquer un minimum, car les Regex c'est très lisible généralement...


---------------
Si vous ouvrez un sujet merci de ne pas le "laisser mourir" subitement et de le marquer comme "résolu" le cas échéant!
n°2454295
dhenin
Posté le 14-09-2023 à 15:30:26  profilanswer
 

Ok J'ai un script qui fonctionne. J'ouvre un nouveau topic. Ce sujet me semble peu traité autant laisser une trace accessible. La suite est là : https://forum.hardware.fr/hfr/Progr [...] 8478_1.htm


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  [résolu] regex : extraire entre une paire d'accolades matchées

 

Sujets relatifs
[regex] url rewriting en russe...Pb d'url rewrite + regex
[regex-js] ma petite expression régulière javascript...Extraire musique d'un jeux
[C++] Extraire images d'un fichier mxf avec Mxflibjava Regex : Je recherche le moyen d'extraire des lettres
[RegEx] extraire donné entre un div ?extraire un bout de chaîne avec un regex
REGEX - extraire une chaine 
Plus de sujets relatifs à : [résolu] regex : extraire entre une paire d'accolades matchées


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR