6

我有一个文件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 的倍数时,它会在输出文件的末尾插入额外的换行符。当字符串长度是 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")
}

它仍然存在同样的问题。

我在这里寻找,在这里但仍然无法解决。

4

4 回答 4

10
spurt "out.txt", "test.txt".IO.comb(3).join("\n")
于 2020-05-18T17:57:55.020 回答
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
于 2020-05-21T15:44:02.217 回答
2

正确答案当然是使用.comband .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;
}

这是有效的,因为<返回Trueor False

由于True == 1False == 0x运算符最多重复\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;
}
于 2020-05-19T18:53:18.473 回答
2

在命令行提示符下,以下三个单行解决方案。

使用comband 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

或者,使用comband rotor(最后丢弃不完整的 3 个字母):

~$ echo 'StringsplittingskillsX' | perl6 -ne '.join.put for .comb.rotor(3);'
Str
ing
spl
itt
ing
ski
lls
于 2021-12-17T13:33:02.607 回答