У меня есть этот простой ввод

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

Я использую Perl для определения закономерностей между двумя внешними скобками-разделителями { и } и рандомизирую поля внутри с помощью внутреннего разделителя ;.

Я получаю этот вывод

I have green fruit and cup of coffee

Это мой рабочий Perl-скрипт

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

Моя задача - обработать этот формат ввода

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

Как я понял, скрипт должен пропускать внешние закрывающие скобки { ... } в первой части текста, в которой есть текст внутри с открывающими и закрывающими скобками:

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

Он должен выбрать случайную часть, например эту

{red;green;orange} fruit

Или

cup of {tea;coffee;juice}

Затем все идет глубже:

green fruit

После обработки всего текста результатом может быть любой из следующих

I have red fruit and fresh burger.
I have cup of tea and nice sandwich
I have green fruit and nice burger.
I have cup of coffee and fresh burger.

Скрипт также должен анализировать и рандомизировать следующий текст. Например

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 }

Пример вывода может быть

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.
6
kempinski 24 Дек 2015 в 16:02

3 ответа

Лучший ответ

Хороший вызов. Что вам нужно сделать, так это найти набор подтяжек без внутренних скобок и выбрать оттуда случайный предмет. Это нужно делать глобально. Это заменит только скобки «уровня 1». Вам нужно перебирать строку до тех пор, пока совпадений не будет найдено.

use v5.18;
use strict;
use warnings;

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);

Образец вывода

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
2
glenn jackman 28 Дек 2015 в 18:41

Решение TXR. Есть много способов подойти к этому.

Предположим, мы читаем данные со стандартного ввода. Как насчет того, чтобы прочитать данные в записях, которые разделены не обычным символом новой строки, а шаблоном выбора в фигурных скобках? Мы делаем это, создавая объект адаптера записи поверх стандартного входного потока. Третий аргумент функции record-adapter - это Логическое значение, которое указывает, что мы хотим сохранить завершающий разделитель (часть, которая соответствует регулярному выражению, ограничивающему записи).

Таким образом, если данные выглядят так foo bar {bra;ces} xyzzy {a;b;c} d\n, они превращаются в следующие записи: foo bar {bra;ces}, xyzzy {a;b;c} и d\n.

Затем мы обрабатываем эти записи, как если бы они были строками текста, используя язык извлечения. Они делятся на два шаблона: линии, которые заканчиваются фигурными скобками, и линии, которые не заканчиваются. Последние просто повторяются. Первые обрабатываются как требуется при замене случайных скобок.

Мы также инициализируем *random-state*, чтобы ГПСЧ с засеянными данными для создания различной псевдослучайной последовательности при каждом запуске. Если make-random-state не задано аргументов, создается объект случайного состояния, инициализированный из системных параметров, таких как идентификатор процесса и системное время:

@(do (set *random-state* (make-random-state)))
@(next @(record-adapter #/{[\w;]+}/ *stdin* t))
@(repeat)
@  (cases)
@*text{@switch}
@    (do (put-string `@text@(first (shuffle (split-str switch ";")))`))
@  (or)
@text
@    (do (put-string text))
@  (end)
@(end)

Тестовый забег:

$ cat data
I have {red;green;orange} fruit and cup of {tea;coffee;juice}.
$ txr rndchoose.txr < data
I have red fruit and cup of tea.
$ txr rndchoose.txr < data
I have orange fruit and cup of tea.
$ txr rndchoose.txr < data
I have green fruit and cup of coffee.
0
Kaz 9 Май 2016 в 22:58

Избегать жадности - хорошая мысль, но она не совсем помогает. И вы можете добавить петлю:

perl -plE 'while(s!\{([^{}]*)\}!@x=split/;/,$1;$x[rand@x]!ge){}'

Обратите внимание, что в вашем образце ввода есть несогласованные фигурные скобки, поэтому, похоже, выводится ложный '}'

3
William Pursell 24 Дек 2015 в 13:32