$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
我需要一个函数来打印 str 的随机变化。例如:
Hi Ann
Hello Polly
....
....
有什么想法吗?
$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
$str =~ s{
\[ ( [^\]]* ) \]
}{
my @choices = split /\|/, $1;
$choices[rand(@choices)]
}xeg;
say $str;
只需从集合中生成两个随机数{0,1,2}
并分别构建您的问候语。例如:如果生成的数字是1
and 2
,那么你输出'Hello Polly'
。如果2
和0
,那么'Aloha Kate'
。
我会使用列表和列表包来做到这一点,shuffle
并pairwise
想到,例如:
use 5.010;
use List::Util qw /shuffle/;
use List::MoreUtils qw/pairwise/;
$, = " ";
@greetings = shuffle qw(Hi Hello Aloha);
@names = shuffle qw(Kate Ann Polly);
pairwise { say $a, $b } @greetings, @names;
示例输出:
Hello Polly
Aloha Ann
Hi Kate
如果您对字符串格式感到困惑,可以将其转换为列表,如下所示:
$str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
($greetings, $names) = $str =~ /\[([^]]+)\] +\[([^]]+)\]/;
@greetings = shuffle split /\|/, $greetings;
@names = shuffle split /\|/, $names;
将两个数组中的两个随机元素组合起来相当简单,@OleksandrBondarenko 回答了这个问题。更有趣的问题是如何从该字符串中获取数据结构。
更改输入格式。您需要两个列表/数组,而不是字符串。如果您可以更改您的 API 或接口,那么这样做可能比使用此字符串表示更容易
从该字符串和eval
它创建 Perl 代码。虽然这很容易,但这是一个严重的安全问题,因此这应该只应用于输入众所周知且受信任的一次性问题:
my $str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
$str =~ s/ /,/g; # '[Hi|Hello|Aloha],[Kate|Ann|Polly]'
$str =~ s/\|/","/g; # '[Hi","Hello","Aloha],[Kate","Ann","Polly]'
$str =~ s/\[/["/g; # '["Hi","Hello","Aloha],["Kate","Ann","Polly]'
$str =~ s/\]/"]/g; # '["Hi","Hello","Aloha"],["Kate","Ann","Polly"]'
my @arrayrefs = eval $str; # (["Hi","Hello","Aloha"],["Kate","Ann","Polly"])
my @greetings = @{shift @arrayrefs};
my @names = @{shift @arrayrefs};
不要在生产代码中这样做,因为字符串可能包含任意代码,可能会对您的计算机、文件或安全性造成严重损坏。
正确处理和解析数据。虽然这有时很困难,但它是最安全的解决方案。
my $str = '[Hi|Hello|Aloha] [Kate|Ann|Polly]';
my @strings = split /(?<=\])\s+(?=\[)/, $str;
# for each $string in @strings:
$string =~ s/^\[//; #
$string =~ s/\]$//; # or: $string = substr $str, 1, length $str -2;
my @parts = split /\|/, $string
第一个@parts
是问候数组,第二个是名称数组。这个解决方案需要一些我省略的进一步代码。
第一个正则表达式中的环视split
并不是真正必要的,但比对数据格式做出假设要好。