【问题标题】:Randomizing text between delimiters在分隔符之间随机化文本
【发布时间】:2016-03-30 22:11:06
【问题描述】:

我有这个简单的输入

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.

【问题讨论】:

    标签: perl shell text-processing text-parsing


    【解决方案1】:

    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*,以便为 PRNG 播种以在每次运行时产生不同的伪随机序列。如果make-random-state 没有给定参数,它会创建一个随机状态对象,从进程ID和系统时间等系统参数初始化:

    @(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)
    

    试运行:

    $猫数据 我有 {red;green;orange} 水果和一杯 {tea;coffee;juice}。 $ txr rndchoose.txr

    【讨论】:

      【解决方案2】:

      不错的挑战。你需要做的是找到一套没有内牙套的牙套,并从中随机挑选一个物品。你需要在全球范围内这样做。这将只替换“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
      

      【讨论】:

      • 你为什么用srand
      • 我认为有充分的理由,但是(阅读文档)没有。
      【解决方案3】:

      不贪婪是个好主意,但并不完全奏效。你可以添加一个循环:

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

      请注意,您的示例输入具有不匹配的大括号,因此这似乎输出了一个虚假的 '}'

      【讨论】:

        猜你喜欢
        • 2016-03-30
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 2021-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多