2016-03-23 5 views
-3

Der Versuch, etwas wie folgt zu tun.Perl - Erweitern Sie eine Zeichenfolge in eine Liste.

#expand [a] to is, and isn't 
#expand [b] to test, and demo 
my $string = 'This [a] a [b]'; 

so dass im Grunde würde ich mit

my @strings = ('This is a test', 'This isn\'t a test', 'This is a demo', 'This isn\'t a demo'); 

ich dies am Ende getan haben, bevor Rekursion, aber das war auf einer sehr großen Menge von Daten und eine Menge von Regeln, die ich fühle mich wie könnte es ein einfacher Weg mit Map oder Grep oder List :: MoreUtils Ich kann einfach nicht daran denken.

+0

Würde eine akzeptierte Lösung beinhaltet unter Verwendung von s '/ \ [a \]/ist/'auf' $ string'? –

+0

Würde das nicht nur meine ursprüngliche Zeichenfolge ändern. –

+0

Es klingt, als würdest du nach "sprintf" suchen, wenn du nicht mit dem "[a]" - Ding verheiratet bist. – AKHolland

Antwort

2

Bei Eingaben des Formulars

my %dict = (
    a => ["is", "isn't"], 
    b => ["test", "demo"], 
); 

my $template = 'This [a] a [b]'; 

Algorithmus :: Loops Version:

use Algorithm::Loops qw(NestedLoops); 

my @loops; 
for ($template) { 
    if (/\G \[ /xgc) { 
     /\G ([^\]]*) \] /xgc 
     or die("Missing \"]\"\n"); 

     my $var = $1; 
     length($var) 
     or die("Empty \"[]\"\n"); 

     $dict{$var}  
     or die("Unknown var \"$var\"\n"); 

     push @loops, $dict{$var}; 
     redo; 
    } 

    if (/\G ([^\[]+) /xgc) { 
     push @loops, [ $1 ]; 
     redo; 
    } 

    /\G \z /xgc 
     or die("Internal error"); 
} 

my $iter = NestedLoops(\@loops); 
while (my @parts = $iter->()) { 
    print(join('', @parts), "\n"); 
} 

Ausgang:

This is a test 
This is a demo 
This isn't a test 
This isn't a demo 

glob -basierte Version:

$_ = '{'.join(',', map quotemeta($_), @$_).'}' 
    for values(%dict); 

my $glob; 
for ($template) { 
    if (/\G \[ /xgc) { 
     /\G ([^\]]*) \] /xgc 
     or die("Missing \"]\"\n"); 

     my $var = $1; 
     length($var) 
     or die("Empty \"[]\"\n"); 

     $dict{$var} 
     or die("Unknown var \"$var\"\n"); 

     $glob .= $dict{$var}; 
     redo; 
    } 

    if (/\G ([^\[]+) /xgc) { 
     $glob .= $1; 
     redo; 
    } 

    /\G \z /xgc 
     or die("Internal error"); 
} 

while (defined(my $string = glob($glob))) { 
    print($string, "\n"); 
} 

ohne Fehlerprüfung und für diesen speziellen Wörterbuch, kann dies durchaus ein wenig geschrumpft: Sie

$ perl -E'say for glob shift=~s/\[((a)|b)]|(.)/$3?"\Q$3":$1?"{is,isn'\''t}":"{test,demo}"/serg' \ 
    'This [a] a [b]' 
This is a test 
This is a demo 
This isn't a test 
This isn't a demo 
+0

Ich meine, das sieht fast identisch mit meinem ersten Versuch aus. Ich denke, ich werde das einfach wiederverwenden. Ich hatte gehofft, dass es eine One-Liner-Lösung geben könnte. –

+0

Sie können keinen oneliner erwarten, wenn Sie Ihr eigenes Vorlagensystem erfinden. – ikegami

+0

Danke, du bist der, auf den ich gehofft hatte. –