【问题标题】:Extract a word between brackets and replace it in a sentence提取括号之间的单词并将其替换为句子
【发布时间】:2022-01-25 07:53:50
【问题描述】:

假设我有这句话

It's {raining|snowing|cold} outside

我想要的是在括号之间随机提取一个单词,我用awk -vRS="}" -vFS="|" '{print $2}' 做了这个(仍在努力随机提取它们)。输出通常是第二个单词,在我们的例子中是snowing

问题是输出只有snowing,而我想要的实际输出类似于It's snowing outside,那么如何从括号中提取任何单词并仅替换为一个单词。

【问题讨论】:

  • 如果要随机选择三个单词中的一个,为什么要选择这么复杂的方法呢?制作一个包含三个单词的数组并使用RANDOM % 3 选择其中一个。
  • 那句话只是一个例子,实际上我有更多的句子在括号内包含这样的词,我设法只提取了第二个词,这应该不是问题,我出于好奇询问了随机化
  • 我会解析句子以生成数组,然后选择(通过随机化或其他方式)。
  • 很公平,如何将括号内的单词替换为仅从中提取的一个单词
  • 你想走捷径。也许它存在,但我会首先为您正在处理的格式编写一个解析器,以获取一组数据并从中选择一个单词。如果您只需要 一个 单词,而不管哪个单词都没有关系,您可以 regex 去掉可选单词。

标签: linux bash perl awk


【解决方案1】:
echo "It's {raining|snowing|cold} outside" |\
  perl -pe 's/\{(.*?)\}/(split("[|]",$1)[rand(3)]/e'

或任意数量的天气条件:

echo "It's {raining|snowing|cold} outside" |\
  perl -pe 's/\{(.*?)\}/@a=split("[|]",$1); $a[rand(@a)]/e'

【讨论】:

    【解决方案2】:

    由于您需要通过查找和替换字符串的一部分来重写字符串,因此正则表达式是合适的

    use warnings;
    use strict;
    use feature 'say';
    
    sub pick_one { 
        my ($pattern) = @_; 
        my @choices = split /\|/, $pattern; 
        return $choices[int rand @choices]; 
    }
    
    my $sentence = q(It's {raining|snowing|cold} outside); 
    
    $sentence =~ s/\{ ( [^}]+ ) \}/pick_one($1)/ex; 
    
    say $sentence; 
    

    /e 修饰符使其将替换端评估为代码,然后将生成的值用作替换。所以我们在那里运行一个选择发生的子。将它放在子中是以后改进/更改的好方法,在子中实现。

    使用rand 选择数组@choices 的一个元素。其上限的表达式在标量上下文中求值,因此我们可以直接使用 @choices 数组,因为它的长度最终会被使用。

    【讨论】:

      【解决方案3】:

      一个有趣的解决方案是(ab)使用 Perl 的glob 函数来生成可能组合的列表。需要注意的是,您不能在字符串中使用 glob 元字符。例如:

      use strict;
      use warnings;
      use Data::Dumper;
      use feature 'say';
      
      my $str = "It's {freaking|fudging} {raining|snowing|cold} outside";
      
      $str =~ s#({[^}]+})#$1 =~ s/\|/,/gr#ge;   # replace | with , inside curly braces
      my @list = glob $str;
      print Dumper \@list;
      
      say "Our random string: " . $list[ int rand(@list) ];
      

      输出:

      $VAR1 = [
                'It\'s freaking raining outside',
                'It\'s freaking snowing outside',
                'It\'s freaking cold outside',
                'It\'s fudging raining outside',
                'It\'s fudging snowing outside',
                'It\'s fudging cold outside'
              ];
      Our random string: It's fudging cold outside
      

      【讨论】:

      • 机智!小幅简化:$str =~ s#({.+?})#$1 =~ s/\|/,/gr#ge
      • @sizif 我对非贪婪量词很熟悉,但在这种情况下我更喜欢使用[^}]+
      【解决方案4】:

      简单的bash,不使用任何外部命令:

      #!/bin/bash
      
      while read -r line; do
          if [[ $line =~ (.*)\{([^}]*)}(.*) ]]; then
              IFS='|' read -ra words <<< "${BASH_REMATCH[2]}"
              line=${BASH_REMATCH[1]}${words[RANDOM%${#words[*]}]}${BASH_REMATCH[3]}
          fi
          printf '%s\n' "$line"
      done < file
      

      【讨论】:

        【解决方案5】:
        echo "It's {raining|snowing|cold} outside"|awk -F"[{|}]" -v w="$(shuf -i 2-4 -n 1)" '{print $1$w$NF}'
        

        【讨论】:

          【解决方案6】:

          在每个 Unix 机器上的任何 shell 中使用任何 awk:

          $ cat tst.awk
          BEGIN { srand() }
          match($0,/\{[^}]+}/) {
              wordList = substr($0,RSTART+1,RLENGTH-2)
              numWords = split(wordList,words,/[|]/)
              wordNr = int(rand() * numWords + 1)
              $0 = substr($0,1,RSTART-1) words[wordNr] substr($0,RSTART+RLENGTH)
          }
          { print }
          

          $ awk -f tst.awk file
          It's snowing outside
          
          $ awk -f tst.awk file
          It's cold outside
          

          有关其随机性的详细信息,请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Numeric-Functions 上的rand()(和srand())。

          【讨论】:

            【解决方案7】:

            jq 是单行的:

            echo "It's {raining|snowing|cold} outside" | \
            jq -rR --argjson rand $RANDOM 'gsub("{(?<words>[^}]+)}"; .words | split("|") | .[$rand % length])'
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-03-06
              • 1970-01-01
              • 2017-09-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-11-24
              相关资源
              最近更新 更多