2008-12-05 4 views
3

Je suis en train de mettre les choses entre parenthèses dans la valeur d'un attribut src dans une balise img:

while(<TOCFILE>) 
{ 
    $toc_line = $_; 
    $toc_line =~ s/<inlineFig.*?(\.\.\/pics\/ch09_inline99_*?\.jpg)*?<\/inlineFig>/<img src="${1}" alt="" \/\>/g; 
    $new_toc_file .= $toc_line; 
} 

Je pensais voir des étiquettes comme celui-ci dans la sortie:

<img src="../pics/ch09_inline99_00" alt="" /> 

Mais au lieu que je reçois:

<img src="" alt="" /> 

Répondre

12

Il y a une erreur dans votre regex afin que la phrase ne sera jamais correspondre à quelque chose:

inline99_*?\.jpg 
     ^^^ 

Je pense que vous avez oublié \d en face de l'étoile, à en juger par les données d'exemple que vous essayez de faire correspondre.

Vous ne demandez même pas que cela corresponde, car vous mettez un *? après le groupe capturé. Donc, ça ne correspond à rien. Donc c'est ce que vous obtenez: rien.

En plus:

($PATTERN)*? 

ne capturera la dernière chose qu'il correspondait. Ce n'est probablement pas ce que vous voulez non plus. Par exemple:

$_ = 'one two three'; 
s/(\w+\s*)*/$1/; 
print; 

imprime "trois".

+0

En effet. Presque chaque fois que j'ai ce problème, c'est un problème avec mon modèle. –

3

1) pourrait utiliser quelques exemples de ce que vous êtes en train d'analyser.

2) si l'utilisation de l'utilisation « x » à la fin de l'expression, vous pouvez mettre l'espace blanc et commentaires dans l'expression régulière pour le rendre plus compréhensible

3) En outre, en brisant vers le bas, vous ll remarquera que la deuxième partie du contenu à l'intérieur de() manquait le match pour les nombres ... au lieu de chercher 0 ou plus '_', et se brisant quand il voyait les nombres, donc ne correspondant pas.

while(<TOCFILE>) 
{ 
    $toc_line = $_; 
    $toc_line =~ 
     s/     # replace the follwoing  

     <inlineFig      # match this text    
     .*?       # then any characters until the next sequence matches 
     (        # throw the match into $1 
      \.\.\/pics\/ch09_inline99_ # ..\pics\cho9_inline99_ 
      \d*?\.jpg     # folowed by 0 or more numbers 
     )*?       # keeping doing that until the next sequence matches 
     <\/inlineFig>     # match this text 

    /    # with the follwoing 


     <img src="${1}" alt="" \/\> # some text and the result of $1 above. 

     /xg; # <- the x makes it ignore whitespace and #comments 
    $new_toc_file .= $toc_line; 
} 

4) comme mentionné,() *? retourne seulement le dernier match dans $ 1, mais cela ne devrait pas être un problème si votre entrée ne va avoir qu'un certain format.

1

Corrigez votre motif, comme suggéré par bart, et envisagez d'utiliser la variable "topic" $ _ au lieu d'affecter explicitement les données lues du handle de fichier à une autre variable.

#!/usr/bin/perl 

use warnings; 
use strict; 

my $new_toc_file; 

{ 
    # localizing $_ protects any existing value in the global $_ 
    # you should localize $_ even if you choose to assign it to a variable 

    local $_; 

    while(<DATA>) { 
     # in the absence of the bind operator =~, s/// operates against $_ 
     s!<inlineFig.*?(\.\./pics/ch09_inline99_.*?\.jpg)</inlineFig>!<img src="$1" alt="" />!g; 
     $new_toc_file .= $_; 
    } 
} 

print $new_toc_file, "\n"; 

__END__ 
<inlineFig>../pics/ch09_inline99_00.jpg</inlineFig> 
+0

bonne pratique de codage est généralement d'utiliser une variable descriptive ... peut-être tandis que (my $ topic = ) {} ... éviter la possibilité de réécrire $ _ tout à fait. –

+0

Avec une substitution, vous voudrez souvent laisser les données d'origine telles quelles et en modifier une copie. Dans un court exemple, cela semble étrange, mais ce n'est qu'un exemple court plutôt qu'un programme utile. –

Questions connexes