2009-04-10 4 views
5

J'ai besoin d'écrire un script Perl pour lire dans un fichier, et supprimer quelque chose à l'intérieur de <>, même si elles sont sur des lignes différentes. Autrement dit, si l'entrée est:Comment faire pour supprimer des caractères entre < and > dans Perl?

Hello, world. I <enjoy eating 
bagels. They are quite tasty. 
I prefer when I ate a bagel to 
when I >ate a sandwich. <I also 
like >bananas. 

Je veux que la sortie soit:

Hello, world. I ate a sandwich. bananas. 

Je sais comment faire si le texte est sur 1 ligne avec une expression régulière. Mais je ne sais pas comment le faire avec plusieurs lignes. En fin de compte, je dois pouvoir supprimer de manière conditionnelle les parties d'un modèle afin de pouvoir générer des fichiers paramétrés pour les fichiers de configuration. Je pensais que perl serait une bonne langue, mais je suis toujours en train de comprendre.

Modifier: Aussi besoin de plus de 1 instance de <>

Répondre

4
local $/; 
my $text = <>; 
s/<.*?>//gs; 
print $text; 
+0

Si votre chaîne ressemble à ceci: ghi>, votre regex quitte 'ghi>'.Si les parenthèses imbriquées ou échappées et d'autres cas pervers "n'arrivent jamais" l'expression rationnelle est bien. Pour gérer les cas pervers, utilisez Text :: Balanced, même si l'interface est bizarre. – daotoad

6

Vous pouvez consulter un module Perl Text::Balanced, une partie de la distribution de base. Je pense que ça va t'aider. Généralement, on veut éviter les regexes pour faire ce genre de chose SI le texte sujet est susceptible d'avoir un ensemble interne de délimiteurs, il peut devenir très salissant.

+0

Un bon conseil, mais pas nécessaire dans ce cas. Je vais certainement garder à l'esprit cependant. – rlbond

6

En Perl:

#! /usr/bin/perl 
use strict; 

my $text = <>; 
$text =~ s/<[^>]*>//g; 
print $text; 

Le regex substitue tout en commençant par un < à travers le premier> (y compris) et il remplace rien. Le g est global (plus d'une fois).

EDIT: incorporé les commentaires de Hynek et le chaos

+0

+1 Bel exemple (complet)! –

+0

C'est un peu inefficace. Pour le diviser et rejoindre à nouveau. perl -0777 -pe 's/<[^>] *> // gm' –

+0

le modificateur/m n'aide pas. Cela signifie «traiter comme multiligne», c'est-à-dire correspondre à^et $ aux nouvelles lignes, et non «c'est multiligne»./s, traiter en tant que ligne unique, est en fait plus ce que vous voulez, mais vous n'en avez pas besoin parce que votre motif n'est pas concerné par les espaces. – chaos

1

Inefficace façon one-liner

perl -0777 -pe 's/<.*?>//gs' 

même que le programme

local $/; 
my $text = <>; 
s/<.*?>//gs; 
print $text; 

Cela dépend de la taille du texte que vous voulez convertir ici est plus efficace one-liner consommant ligne par ligne

perl -pe 'if ($a) {(s/.*?>// and do {s/<.*?>//g; $a = s/<.*//s;1}) or $_=q{}} else {s/<.*?>//g; $a = s/<.*//s}' 

même que le programme

my $a; 
while (<>) { 
    if ($a) { 
     if (s/.*?>//) { 
      s/<.*?>//g; 
      $a = s/<.*//s; 
     } 
     else { $_ = q{} } 
    } 
    else { 
     s/<.*?>//g; 
     $a = s/<.*//s; 
    } 
    print; 
} 
+0

Comme indiqué sur la réponse de CoverosGene,/m n'est pas nécessaire ou utile. – chaos

+0

Oui, vous avez raison. –

Questions connexes