当我尝试解析多行字符串(用制表符分隔的字符串),目的是查找用制表符分隔的所有值时,偶然发现了“奇怪”的行为,使用连续的两个分割:
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
“奇怪”行为出现在所得序列的3d和5th成员中。似乎一行的“预期”最后一个字符串与后续行的第一个字符串重叠。
我的期望是:
("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
但是我的问题是关于“错误”代码的内部工作的。 Raku是怎么得出这个结果的?
答案 0 :(得分:9)
您正在分割第一个分割的结果,它是一个列表; split方法将强制将调用的内容强制转换为字符串,然后将其拆分。列表将通过其Str
方法字符串化为由单个空格分隔的成员。这就是为什么某些结果字段具有两个L和C对以及它们之间有一个空格的原因。
这将为您提供所需的结果:
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以便将其 slipped 放入更大的数组中。
答案 1 :(得分:4)
如果您希望拆分将单个片段作为一个列表而不是列表提供,则可以使用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
时,分隔符本身将在结果列表中。