将字符串拆分为固定长度的块,并在Raku

时间:2020-05-18 17:43:24

标签: string raku rakudo

我有一个文件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")
}

仍然遇到相同的问题。

我寻找了herehere,但仍然无法解决。

3 个答案:

答案 0 :(得分:9)

require '../vendor/autoload.php';
require_once '../config.php';

$id = $_POST['id'];
$topic = $_POST['topic'];
$type = $_POST['type'];
$start_time = $_POST['start_time'];
$duration = $_POST['duration'];
$agenda = $_POST['agenda'];

$params = array(
        'topic' => $topic,
        'type' => $type,
        'start_time' => $start_time,
        'duration' => $duration,
        'agenda' => $agenda,
        'password' => '123456'
);

$provider = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => CONEXAO_API['clientId'],    
    'clientSecret'            => CONEXAO_API['clientSecret'],   
    'redirectUri'             => CONEXAO_API['redirect_url'],
    'urlAuthorize'            => 'https://zoom.us/oauth/authorize',
    'urlAccessToken'          => 'https://zoom.us/oauth/token',
    'urlResourceOwnerDetails' => 'https://api.zoom.us/v2/users/me'
]);

$options['body'] = json_encode( $params );
$options['headers']['Content-Type'] = 'application/json';
$options['headers']['Accept'] = 'application/json';


$request = $provider->getAuthenticatedRequest( 'PATCH', 
        'https://api.zoom.us/v2/meetings/'.$id,
        unserialize($_SESSION['token']), 
        $options
);

$retorno =  $provider->getParsedResponse($request);

var_dump($retorno);

答案 1 :(得分: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

答案 2 :(得分:2)

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

之所以可行,是因为<返回TrueFalse

由于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;
}