2009-12-14 4 views
3

J'ai une chaîne comme ceci:découpant une chaîne en jetons et le stockage des délimiteurs en Perl

a b c  d 

Je traiter ma chaîne comme ceci:

chomp $line; 
    my @tokens = split /\s+/, $line; 
    my @new_tokens; 
    foreach my $token (@tokens) {  
     push @new_tokens, some_complex_function($token); 
    } 
    my $new_str = join ' ', @tokens; 

J'aimerais adhérer à nouveau la chaîne avec l'espace d'origine. Y a-t-il un moyen de stocker les espaces et de les réutiliser plus tard? Ou est-ce que ça va être une énorme douleur? C'est principalement cosmétique, mais je voudrais préserver les espaces d'origine de la chaîne d'entrée.

Répondre

15

Si vous divisez avec une expression régulière avec des parenthèses de capture, le motif de répartition sera inclus dans la liste des résultats (voir perldoc -f split):

my @list = split /(\s+)/, 'a b c  d'; 
print Data::Dumper::Dumper(\@list); 

VAR1 = [ 
      'a', 
      ' ', 
      'b', 
      ' ', 
      'c', 
      '  ', 
      'd' 
     ]; 
4

Juste divisés sur les limites des mots:

split /\b/, $line; 

Pour exemple, cela donnera:

('a',' ','b',' ','c','  ','d') 

EDIT: Comme brian d foy a souligné, \b utilise les classes de personnages mal, Suite à mon idée originale, je suis venu avec l'utilisation d'assertions de look-around. Cela semble plus compliqué que la réponse de l'éther, cependant:

split /(?:(?<=\S)(?=\s)|(?<=\s)(?=\S))/, $line; 
+1

Cela peut diviser par mégarde sur des choses qui ne sont pas des frontières blancs. –

+0

Merci de le signaler! J'ai écrit la réponse originale sans penser à '\ w' vs' \ s'. Edité ma réponse en conséquence. – hillu

3

Pourquoi ne faites-vous pas simplement: my $new_str = uc($line);?

UPDATE - original uc() est juste un raccourci pour "fonction plus complexe".

Eh bien, vous pouvez généralement aussi:

$line =~ s/(\S+)/more_complex_function($1)/ge; 
+1

Parce que mon cas réel est plus compliqué, et ce n'est qu'un exemple. –

Questions connexes