Как я могу включать переменную в Perl printf выражение?

Как я могу включать переменную в printf выражение?

Вот мой пример:

printf "%${cols}s", $_;

Где $cols число столбцов и $_ строка.

Оператор приводит к "Недопустимому преобразованию" предупреждение.

Проблема закончила тем, что была, что я забыл громко жевать переменную. Gah. Спасибо все.

7
задан Lou 26 February 2010 в 18:43
поделиться

6 ответов

Я не могу воспроизвести вашу проблему. Следующий код работает нормально:

use strict;
use warnings;

my $cols=40;
while (<>) {
    printf "%${cols}s\n", $_;
}

Он печатает любую входную строку, используя не менее 40 столбцов ширины.

-121--3772218-

Интерполяционная переменная $ cols должна быть числом, скажем 10, поэтому

"%${cols}s"

должна быть интерполирована и эквивалентна

"%10s"

, который является допустимым форматом последовательности.

Если бы $ cols был чем-то другим , чем число или допустимый формат последовательности, вы бы получили предупреждение.

Например, если:

$cols = "w";

, что приведет к «% ws» в качестве последовательности формата - с указанием ошибки вы цитируете:

Invalid conversion in printf: "%w"

Допустимые сведения о формате можно найти здесь .

-121--3772211-

Я выяснил вашу конкретную проблему. Код правильный. Однако я полагаю, что $ cols может быть числом, считанным из пользовательского ввода, скажем так:

my $cols = <STDIN>;

Это работает, и в числовом контексте $ cols будет выглядеть как число, но проблема в том, что $ cols не появляется в числовом контексте здесь. В последовательность контексте это означает, что вместо расширения до «% 5s» формат последовательности расширяется до «% 5\ns» . Новая линия там сковывает последовательность формата.

Измените код, в котором вы читаете $ cols , на следующий:

chomp(my $cols = <STDIN>);

См. документацию по chomp , так как ее можно использовать и для чтения других входных данных.

9
ответ дан 6 December 2019 в 05:55
поделиться

Мне кажется, что следующее работает:

#!/bin/perl5.8 -w
use strict;
my $cols = 5;
my $a = "3";
printf "%${cols}d\n", $a;

дает

28$ ./test.pl
    3

29$ 
1
ответ дан 6 December 2019 в 05:55
поделиться

Ваша интерполированная переменная $cols выглядит так, как будто она должна быть числом, скажем 10, поэтому

"%${cols}s"

должна интерполироваться и быть эквивалентной

"%10s"

что является допустимой строкой формата.

Однако если $cols будет чем-то другим, чем число или допустимая форматная строка, то вы получите предупреждение.

Например, если:

$cols = "w";

в качестве строки формата будет "%ws", то возникнет ошибка, которую вы цитируете:

Invalid conversion in printf: "%w"

Информация о допустимом формате может быть найдена здесь.

11
ответ дан 6 December 2019 в 05:55
поделиться

Никто никогда не был уволен за выбор Java

-121--3302885-

Использование double fun () , а не double (* fun) () является архаичной формой, которая действительна только в стандарте C и никогда в C++, и если я правильно помню, только при объявлении аргумента функции. (во многом как ary [] , что является законным для аргумента функции, но не для неинициализированной переменной)

Поскольку невозможно (в языке C) передать функцию по значению другой функции, компилятор просто принял двойную забаву () , чтобы обозначить указатель на функцию, которая вернула двойную.

Это действительно (но архаично. попал в немилость)

-121--3950482-

Всегда используйте * в спецификаторе формата для однозначного указания переменной ширины! Это аналогично совету использовать printf «% s», $ str , а не printf $ str .

В документации по perlfunc на sprintf :

(минимальная) ширина

Аргументы обычно форматируются так, чтобы иметь ширину, необходимую для отображения заданного значения. Можно переопределить ширину, поместив здесь число, или получить ширину из следующего аргумента (с помощью * ) или из указанного аргумента (например, с помощью * 2 $ ):

 printf «<% s >», «a»; # печатает «< a >»
printf "<% 6s >", a "; # печатает" < a > "
printf «<% * s >», 6, «a»; # печатает «< a >»
printf '<% * 2 $ s >', «a», 6; # печатает «< a >»
printf «» <% 2s > «», long; # печатает «» < long > «» (не усекается)

Если ширина поля, полученная с помощью * , отрицательна, она имеет тот же эффект, что и флаг - : левое выравнивание.

Например:

#! /usr/bin/perl

use warnings;
use strict;

my $cols = 10;
$_ = "foo!";
printf "%*s\n", $cols, $_;
print "0123456789\n";

Вывод:

      foo!
0123456789

При включенной прагматике предупреждений появятся предупреждения для нечисловых аргументов ширины.

6
ответ дан 6 December 2019 в 05:55
поделиться

Ваш текущий метод должен работать

perl -e'my $cols=500; $_="foo"; printf "%${cols}s\n\n", $_;'
3
ответ дан 6 December 2019 в 05:55
поделиться

Я не могу воспроизвести вашу проблему. Следующий код работает нормально:

use strict;
use warnings;

my $cols=40;
while (<>) {
    printf "%${cols}s\n", $_;
}

Он печатает любую строку ввода шириной не менее 40 столбцов.

1
ответ дан 6 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: