在 Raku 上,我们如何从相应的正则表达式捕获中单独填写多个变量

use*_*456 7 raku

最简单的 Raku 是如何从正则表达式捕获的结果中按相应的顺序填充这么多单独的变量
(就像 Perl 一样) my ($a, $b $c, $d, $e)= 'hello' =~ m{ ^(h) (e) (l) (l) (o) }x

)?

尝试这样的:

> my ($a, $b, $c, $arr);
[<$a $b $c>]= 'hello world' ~~ m{ (h)(e)(l)lo };
say "\n=$a\n=$b\n=$c"

Use of uninitialized value element of type Any in string context.
    Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful.
      in block <unit> at <unknown file> line 1
Run Code Online (Sandbox Code Playgroud)

...

失败了。
请给出正确且最接近Perl的类似方式。

rai*_*iph 9

长话短说

\n
 my ($a, $b, $c) =   \'hello\' =~ m{ ^(h) (e) (l) (l) (o) }x ; # Perl\n my ($a, $b, $c) = |(\'hello\' ~~ m{ ^(h) (e) (l) (l) (o) }) ; # Raku\n
Run Code Online (Sandbox Code Playgroud)\n

我的 Perl 和 Raku 代码之间的差异

\n
\n

添加|( ... )

\n

在 Perl 中,匹配操作通常返回一个字符串或字符串列表。

\n

Raku 中的情况类似,除了Match返回的是对象而不是字符串,并且在 Perl 开发人员可能需要一组字符串的情况下通常只返回一个。您的场景就是一个例子。

\n

(这种额外的复杂性是为了使一般解析的额外功能和实用性能够轻松、自然且自动地可用而进行的权衡。有关此问题的更多讨论,请参见使用Raku从文件中提取.bib。)

\n

幸运的是,如果您将Match对象视为字符串,它会自动强制转换为字符串。类似地,如果你将一个Match对象视为一个列表,那么它会自动强制转换为一个列表。

\n

(这是 Raku 中的一个普遍主题;如果您将一种类型的对象视为另一种类型,并且总的来说,考虑到所涉及的两种类型,它总是自动强制强制是有意义的,那么它这样做。)

\n

如果一个对象类型表面上是“单数”,但也自然具有“复数”方面(例如,它充当“子项”的“父项”),那么如果您将其视为复数,则它可能支持自动强制转换为复数事物事物。例如,诸如此类的操作可以用作列出编号的子项(以及列出命名的.list子项)的方式。.hash

\n

如果给定的“单一”类型的类/对象支持它,则许多方法中的另一种方法是下标:

\n
say (\'foo\' ~~ m{ (.) (.) })[*];                          # (\xef\xbd\xa2f\xef\xbd\xa3 \xef\xbd\xa2o\xef\xbd\xa3)\nsay (\'foo\' ~~ m{ (.) (.) $<I\'m-named>=(.) })<I\'m-named>; # \xef\xbd\xa2o\xef\xbd\xa3\n
Run Code Online (Sandbox Code Playgroud)\n

对于我对这个答案的 2023 年更新,我使用了 JJ 的建议|(...)。

\n
\n

~~代替~=

\n

Raku~~是一个通用的“智能匹配”运算符,可以在其左侧和右侧获取多种类型的数据。它的作用之一是取代 Perl 的正则表达式匹配运算符~=。

\n
\n

{ ... }代替{ ... }x

\n

在 Perl 中,正则表达式中的顶级空格是模式的一部分,除非您附加x副词/选项。但在乐却并非如此。

\n

关于您收到的错误消息

\n
[<$a $b $c>]= \'hello world\' ~~ m{ (h)(e)(l)lo };\n
Run Code Online (Sandbox Code Playgroud)\n

我认为您的作业[<$a $b $c>]= ...并没有像您想象的那样进行。

\n

首先也是最重要的,<...>与 Perl 的“引号”( ) 功能类似qw,将 视为$foo文字字符串 \'$foo\'。所以:

\n
    \n
  • <$a $b $c>相当于(\'$a\', \'$b\', \'$c\').

    \n
  • \n
  • [<$a $b $c>]相当于[\'$a\', \'$b\', \'$c\'].

    \n
  • \n
\n

因此,虽然赋值确实将其结果分配到数组中,但它是通过覆盖包含字符串、等的数组的匿名Scalar容器元素来实现的,而不是更新您声明的变量( \'$a\'\'$b\'$a等)。已通过您的代码绑定到数组的相应元素。

\n

这会导致错误消息重复 3 次,对于$a、$b和各一次$c各一次。

\n

  • ...而Match对象是Captures,即列表和关联同时存在。强制列表或任何将其放入列表上下文的内容都可以。 (2认同)

jjm*_*elo 6

遵循 Raiph 的答案你永远不会做错。但我将尝试解释一下为什么它有效,并提出替代方案。AMatch是Capture一个本质上同时是列表和关联数组的野兽。您想要的是将结果作为列表,与 Perl 中的情况相同。如何提取“列表”部分(或将其强制为列表)?简单:使用显式强制转换(如 Raiph 建议的那样)或尝试将其放入列表上下文中。什么创建列表上下文?展平可以:

my ($a, $b, $c, $d, $e) = |('hello' ~~ m{ ^(h) (e) (l) (l) (o) });
Run Code Online (Sandbox Code Playgroud)

列表绑定也可以:

my ($a, $b, $c, $d, $e) := 'hello' ~~ m{ ^(h) (e) (l) (l) (o) };
Run Code Online (Sandbox Code Playgroud)

问题是每个变量仍然包含一个 Match;你可能想要的是与 Perl 中相同的东西,一个字符串列表。我们可以通过这个组合来实现:

my @array is Array[Str(Match)] = | ('hello' ~~ m{ ^(h) (e) (l) (l) (o) });
Run Code Online (Sandbox Code Playgroud)

我们在右侧获取列表上下文,并通过显式声明带有强制元素的数组,我们得到[h e l l o]结果。

  • JJ,是时候在“文档”中添加一个条目了?“野兽”阶级?;-) (2认同)
  • ```~&lt;&lt;('hello' ~~ m{ ^(h) (e) (l) (l) (o) })``` 使用超级 ```&lt;&lt;``` 来分发 ` ``~``` .Str 强制比赛;) (2认同)