kempinski kempinski - 4 years ago 130
Perl Question

Randomizing text between delimiters

I have next simple input:


I have {red;green;orange} fruit and cup of {tea;coffee;juice}


I use perl to identify specific pattern between two outside delimiters '{' '}' in text and randomize it inside with delimiter ';'. So I'm getting next output:


I have green fruit and cup of coffee


My working perl script:

perl -plE 's!\{(.*?)\}!@x=split/;/,$1;$x[rand@x]!ge' <<< 'I have {red;green;orange} fruit and cup of {tea;coffee;juice}'


Complicated task is to process next input format:


I have { {red;green;orange} fruit ; cup of {tea;coffee;juice} } and {nice;fresh} {sandwich;burger}.





As I understood, script somehow should skip external closing brackets '}' in first text part, which has text inside with opening '{' and closing '}' brackets:


{ {red;green;orange} fruit ; cup of {tea;coffee;juice} }


Here ^ it should choose random part starting from 'upper-level':

Or {red;green;orange} fruit
Or cup of {tea;coffee;juice}


Then it goes deeper:

green fruit





After all text process, we can get next results:



  1. I have red fruit and fresh burger.

  2. I have cup of tea and nice sandwich

  3. I have green fruit and nice burger.

  4. I have cup of coffee and fresh burger.







Script should parse and randomize next text too:


This {beautiful;perfect} {image;photography}, captured with the { {NASA;ESA} Hubble Telescope ; {NASA;ESA} Hubble Space Telescope} }, is the {largest;sharpest} image ever taken of the Andromeda galaxy { {— otherwise known as M31;— known as M31}; [empty here] }.
This is a cropped version of the full image and has 1.5 billion pixels. { You would need more than {600;700;800} HD television screens to display the whole image. ; If you want to display the whole image, you need to download more than {1;2} Tb. traffic and use 800 HD displays }


Example output should be:


This beautiful image, captured with the NASA Hubble Telescope, is the
sharpest image ever taken of the Andromeda galaxy — otherwise known as
M31.
This is a cropped version of the full image and has 1.5 billion
pixels. You would need more than 700 HD television screens to display
the whole image.

Answer Source

Nice challenge. What you need to do is to find a set of braces without interior braces, and pick a random item from in there. You need to do that globally. That will replace just the "level 1" braces. You need to loop over the string until no more matches are found.

use v5.18;
use strict;
use warnings;

srand;

sub rand_sentence {
    my $copy = shift;
    1 while $copy =~ s{ \{ ([^{}]+) \} } 
                      { my @words = split /;/, $1; $words[rand @words] }xsge;
    return $copy;
}

my $str = 'I have { {red;green;orange} fruit ; cup of {tea;coffee;juice} } and {nice;fresh} {sandwich;burger}.';
say rand_sentence($str);
say '';

$str = <<'END';
This {beautiful;perfect} {image;photography}, captured with the { {NASA;ESA}
Hubble Telescope ; {NASA;ESA} Hubble Space Telescope }, is the
{largest;sharpest} image ever taken of the Andromeda galaxy { {— otherwise
known as M31;— known as M31}; [empty here] }. This is a cropped version of the
full image and has 1.5 billion pixels. { You would need more than {600;700;800}
HD television screens to display the whole image. ; If you want to display the
whole image, you need to download more than {1;2} Tb.  traffic and use 800 HD
displays }
END

say rand_sentence($str);

sample output

I have  orange fruit  and fresh sandwich.

This beautiful photography, captured with the  ESA Hubble Space Telescope , is the
largest image ever taken of the Andromeda galaxy  — otherwise
known as M31. This is a cropped version of the
full image and has 1.5 billion pixels.  If you want to display the
whole image, you need to download more than 1 Tb.  traffic and use 800 HD
displays
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download