Split on Split 重叠 [ RAKU ]

Split on Split overlap [ RAKU ]

当我试图解析一个多行字符串(使用制表符分隔的字符串)以查找所有由制表符分隔的值时,我偶然发现了一个 "strange" 行为,使用连续两个拆分:

use v6.d;   # 2020.01 release

my $s = "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3";

say $s.split(/\n/).split(/\t/).raku;

对应的打印输出如下:

("L1:C1", "L1:C2", "L1:C3 L2:C1", "L2:C2", "L2:C3 L3:C1", "L3:C2", "L3:C3").Seq

"strange" 行为在结果序列的第 3d 和第 5 个成员中。好像一行的最后一个字符串"expected"和下一行的第一个字符串有重叠。

我的期望是:

("L1:C1", "L1:C2", "L1:C3", "L2:C1", "L2:C2", "L2:C3", "L3:C1", "L3:C2", "L3:C3").Seq

谁能详细解释一下这种行为的内部机制?

澄清一下,我知道正确的代码是:

$s.split(/\n/)>>.split(/\t/).flat.raku

但我的问题是关于 "wrong" 代码的内部工作原理。 Raku 是如何得出这个结果的?

你拆分的是第一次拆分的结果,是一个列表; split 方法会将调用它的任何内容强制转换为字符串,然后将其拆分。列表将(通过其 Str 方法)字符串化为其由单个 space 分隔的成员。这就是为什么一些结果字段有两个 L 和 C 对以及中间有一个 space 的原因。

这会得到你想要的结果:

say "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3"
    .split("\n")
    .map( *.split( "\t" ).Slip )

因为它拆分了第一个拆分的结果,然后把它转换成一个Slip得到它滑动到更宽的数组中。

如果您希望拆分将各个部分作为一个列表而不是列表列表提供给您,您可以使用 split 方法的变体,它采用分隔符列表作为拆分依据:

say "L1:C1,L1:C2;L1:C3\nL2:C1-L2:C2|L2:C3^L3:C1".split([",", ";", "\n", "|", "^"]).raku;
# output: ("L1:C1", "L1:C2", "L1:C3", "L2:C1-L2:C2", "L2:C3", "L3:C1").Seq

:k:v 副词传递给 split 方法调用会将分隔符作为单独的条目保留在结果列表中;使用 :k 时,该值将是分隔符列表中包含匹配分隔符的索引,使用 :v 时,分隔符本身将出现在结果列表中。