将字符串拆分为固定长度的块并在 Raku 中写在单独的行中
Split string to fixed length chunks and write in separate line in Raku
我有一个文件test.txt
:
Stringsplittingskills
我想读取这个文件并写入另一个文件out.txt
,每行三个字符,如
Str
ing
spl
itt
ing
ski
lls
我做了什么
my $string = "test.txt".IO.slurp;
my $start = 0;
my $elements = $string.chars;
# open file in writing mode
my $file_handle = "out.txt".IO.open: :w;
while $start < $elements {
my $line = $string.substr($start,3);
if $line.chars == 3 {
$file_handle.print("$line\n")
} elsif $line.chars < 3 {
$file_handle.print("$line")
}
$start = $start + 3;
}
# close file handle
$file_handle.close
当字符串的长度不是 3 的倍数时,这运行良好。当字符串长度是 3 的倍数时,它会在输出文件的末尾插入 extra newline。当字符串长度是 3 的倍数时,如何避免在末尾插入新行?
我尝试了另一种更短的方法,
my $string = "test.txt".IO.slurp;
my $file_handle = "out.txt".IO.open: :w;
for $string.comb(3) -> $line {
$file_handle.print("$line\n")
}
仍然遇到同样的问题。
spurt "out.txt", "test.txt".IO.comb(3).join("\n")
正确答案当然是使用.comb
和.join
。
也就是说,这就是您修复代码的方法。
您可以更改 if
行以检查它是否在末尾,并使用 else
.
if $start+3 < $elements {
$file_handle.print("$line\n")
} else {
$file_handle.print($line)
}
我个人会更改它,以便只有添加 \n
是有条件的。
while $start < $elements {
my $line = $string.substr($start,3);
$file_handle.print( $line ~ ( "\n" x ($start+3 < $elements) ));
$start += 3;
}
这是有效的,因为 <
returns True
或 False
。
自 True == 1
和 False == 0
以来,x
运算符最多重复一次 \n
。
'abc' x 1; # 'abc'
'abc' x True; # 'abc'
'abc' x 0; # ''
'abc' x False; # ''
如果您非常谨慎,可以使用 x+?
。
(实际上是 3 个独立的运算符。)
'abc' x 3; # 'abcabcabc'
'abc' x+? 3; # 'abc'
infix:« x »( 'abc', prefix:« + »( prefix:« ? »( 3 ) ) );
如果我要这样构建它,我可能会使用 loop
。
loop ( my $start = 0; $start < $elements ; $start += 3 ) {
my $line = $string.substr($start,3);
$file_handle.print( $line ~ ( "\n" x ($start+3 < $elements) ));
}
或者不是在每行的末尾添加换行符,而是将其添加到除第一行以外的每一行的开头。
while $start < $elements {
my $line = $string.substr($start,3);
my $nl = "\n";
# clear $nl the first time through
once $nl = "";
$file_handle.print($nl ~ $line);
$start = $start + 3;
}
另一种方法使用 substr-rw
。
subset PositiveInt of Int where * > 0;
sub break( Str $str is copy, PositiveInt $length )
{
my $i = $length;
while $i < $str.chars
{
$str.substr-rw( $i, 0 ) = "\n";
$i += $length + 1;
}
$str;
}
say break("12345678", 3);
输出
123
456
78
在命令行提示下,下面三个一行的解决方法。
使用 comb
和 batch
(在末尾保留不完整的 3 个字母):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.join.put for .comb.batch(3);'
Str
ing
spl
itt
ing
ski
lls
X
简化(没有batch
,只有comb
):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.put for .comb(3);'
Str
ing
spl
itt
ing
ski
lls
X
或者,使用 comb
和 rotor
(丢弃末尾不完整的 3 个字母):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.join.put for .comb.rotor(3);'
Str
ing
spl
itt
ing
ski
lls
我有一个文件test.txt
:
Stringsplittingskills
我想读取这个文件并写入另一个文件out.txt
,每行三个字符,如
Str
ing
spl
itt
ing
ski
lls
我做了什么
my $string = "test.txt".IO.slurp;
my $start = 0;
my $elements = $string.chars;
# open file in writing mode
my $file_handle = "out.txt".IO.open: :w;
while $start < $elements {
my $line = $string.substr($start,3);
if $line.chars == 3 {
$file_handle.print("$line\n")
} elsif $line.chars < 3 {
$file_handle.print("$line")
}
$start = $start + 3;
}
# close file handle
$file_handle.close
当字符串的长度不是 3 的倍数时,这运行良好。当字符串长度是 3 的倍数时,它会在输出文件的末尾插入 extra newline。当字符串长度是 3 的倍数时,如何避免在末尾插入新行?
我尝试了另一种更短的方法,
my $string = "test.txt".IO.slurp;
my $file_handle = "out.txt".IO.open: :w;
for $string.comb(3) -> $line {
$file_handle.print("$line\n")
}
仍然遇到同样的问题。
spurt "out.txt", "test.txt".IO.comb(3).join("\n")
正确答案当然是使用.comb
和.join
。
也就是说,这就是您修复代码的方法。
您可以更改 if
行以检查它是否在末尾,并使用 else
.
if $start+3 < $elements {
$file_handle.print("$line\n")
} else {
$file_handle.print($line)
}
我个人会更改它,以便只有添加 \n
是有条件的。
while $start < $elements {
my $line = $string.substr($start,3);
$file_handle.print( $line ~ ( "\n" x ($start+3 < $elements) ));
$start += 3;
}
这是有效的,因为 <
returns True
或 False
。
自 True == 1
和 False == 0
以来,x
运算符最多重复一次 \n
。
'abc' x 1; # 'abc'
'abc' x True; # 'abc'
'abc' x 0; # ''
'abc' x False; # ''
如果您非常谨慎,可以使用 x+?
。
(实际上是 3 个独立的运算符。)
'abc' x 3; # 'abcabcabc'
'abc' x+? 3; # 'abc'
infix:« x »( 'abc', prefix:« + »( prefix:« ? »( 3 ) ) );
如果我要这样构建它,我可能会使用 loop
。
loop ( my $start = 0; $start < $elements ; $start += 3 ) {
my $line = $string.substr($start,3);
$file_handle.print( $line ~ ( "\n" x ($start+3 < $elements) ));
}
或者不是在每行的末尾添加换行符,而是将其添加到除第一行以外的每一行的开头。
while $start < $elements {
my $line = $string.substr($start,3);
my $nl = "\n";
# clear $nl the first time through
once $nl = "";
$file_handle.print($nl ~ $line);
$start = $start + 3;
}
另一种方法使用 substr-rw
。
subset PositiveInt of Int where * > 0;
sub break( Str $str is copy, PositiveInt $length )
{
my $i = $length;
while $i < $str.chars
{
$str.substr-rw( $i, 0 ) = "\n";
$i += $length + 1;
}
$str;
}
say break("12345678", 3);
输出
123
456
78
在命令行提示下,下面三个一行的解决方法。
使用 comb
和 batch
(在末尾保留不完整的 3 个字母):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.join.put for .comb.batch(3);'
Str
ing
spl
itt
ing
ski
lls
X
简化(没有batch
,只有comb
):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.put for .comb(3);'
Str
ing
spl
itt
ing
ski
lls
X
或者,使用 comb
和 rotor
(丢弃末尾不完整的 3 个字母):
~$ echo 'StringsplittingskillsX' | perl6 -ne '.join.put for .comb.rotor(3);'
Str
ing
spl
itt
ing
ski
lls