Как я могу вставить часть строки с пробелами в Perl?

Какую версию вы предпочитаете?

#!/usr/bin/env perl
use warnings; 
use strict;
use 5.010;

my $p = 7; # 33
my $prompt = ' : ';
my $key = 'very important text';
my $value = 'Hello, World!';

my $length = length $key . $prompt;
$p -= $length; 

Вариант 1:

$key = $key . ' ' x $p . $prompt;

Вариант 2:

if ( $p > 0 ) { 
    $key = $key . ' ' x $p . $prompt;
}
else {
    $key = $key . $prompt;
}

say "$key$value"

Ответ 1

Мне не нравится вариант 2, поскольку он вводит ненужный специальный случай.

Я бы реорганизовал конструкцию суффикса prompt:

    # Possible at top of program
    my $suffix =  ( ' ' x $p ) . $prompt;

    # Later...

    $key .= $suffix ;

Ответ 2

Я бы предпочел

sprintf "%-7s : %s", $key, $value;

или

sprintf "%-*s : %s", $p, $key, $value;

вместо всего этого странного материала.

Из sprintf документации:

Символы флага

'-' Преобразованное значение должно быть отрегулировано на границе поля. (Значение по умолчанию - это правильное обоснование.) Преобразованное значение заполняется справа пробелами, а не слева с пробелами или нулями. A '-' переопределяет a 0, если оба даны.

Ширина поля

Необязательная строка десятичной цифры (с ненулевой первой цифрой) с указанием минимальной ширины поля. Если преобразованное значение имеет меньшее количество символов, чем ширина поля, оно будет дополнено пробелами слева (или справа, если установлен флаг левой настройки). Вместо десятичной разрядной строки можно написать '*' или '*m$' (для некоторого десятичного целого m), чтобы указать, что ширина поля задается в следующем аргументе или в m-м аргументе, соответственно, что должно быть типа int. Отрицательная ширина поля принимается за флаг '-', за которым следует положительная ширина поля. Ни в коем случае несущественная или малая ширина поля не вызывает усечения поля; если результат преобразования шире, чем ширина поля, поле расширяется, чтобы содержать результат преобразования.

Ответ 3

Назовите меня старой школой, но я бы использовал printf() или sprintf():

printf "%-33s%s%s\n", $key, $prompt, $value;

Это оставило выравнивание строки $key в 33 пробела, добавляет $prompt и $value и новую строку. Если бы я хотел рассчитать длину для первой части динамически:

printf "%-*s%s%s\n", $len, $key, $prompt, $value;

Так как это одна строка вместо вопроса 4 (вариант 1) или 6 (вариант 2), она выгодно оценивается по шкале лаконичности.

Ответ 4

Я выгляжу немного странно, но это работает (до сих пор):

#!/usr/bin/env perl
use warnings; use strict;
use 5.010;
use utf8;
use Term::Size;
my $columns = ( Term::Size::chars *STDOUT{IO} )[0];
binmode STDOUT, ':encoding(UTF-8)';
use Text::Wrap;
use Term::ANSIColor;

sub my_print {
    my( $key, $value, $prompt, $color, $p ) = @_;
    my $length = length $key.$prompt;
    $p -= $length;
    my $suff = ( ' ' x $p ) . $prompt;
    $key .=  $suff;
    $length = length $key;
    my $col = $columns - $length;
    $Text::Wrap::columns = $col;
    my @array = split /\n/, wrap ( '','', $value ) ;
    $array[0] = colored( $key, $color ) . $array[0];
    for my $idx ( 1..$#array ) {
    $array[$idx] = ( ' ' x $length ) . $array[$idx];
    }
    say for @array;
}

my $prompt = ' : ';
my $color = 'magenta';
my $p = 30;
my $key = 'very important text';
my $value = 'text ' x 40;

my_print( $key, $value, $prompt, $color, $p );