如何使用printf和Term :: ANSIColor的字段宽度?

时间:2015-01-29 12:05:05

标签: perl

如何使用Term::ANSIColor正确左对齐(在固定长度的字段内)一个颜色字符串?这是一个示例程序:

use strict;
use warnings;
use Term::ANSIColor;

my $str1 = "Hello";
my $str2 = (color("bold red") . $str1 . color("reset"));

printf "%-10s : ok\n", $str1;
printf "%-10s : ok\n", $str2;

输出:

enter image description here

预期输出:我希望"ok"字段垂直对齐。

2 个答案:

答案 0 :(得分:3)

问题在于,当您向str2添加颜色时,它会在设置颜色的单词之前将字符串作为前缀加上字符,然后在单词后面加上字符以重置颜色。当你打印这些时,你当然不会看到这些额外的字符。当你的shell解释它们并只打印你选择的颜色的字符串文本。

我们可以在这里看到每个字符串的长度。

use strict;
use warnings;
use Term::ANSIColor;


my $str1 = "Hello";
my $str2 = (color("bold red") . $str1 . color("reset"));

print "length of str1 is: ", length($str1), "\n";
print "length of str2 is: ", length($str2), "\n";

printf "%-10s : ok\n", $str1;
printf "%-10s : ok\n", $str2;

<强>输出

length of str1 is: 5
length of str2 is: 16
Hello      : ok
Hello : ok

printf评估$str2的长度时,它会将其视为16,因为它大于10,所以它不需要用任何空格填充它。

正如@tjd在评论中所说,你需要重新思考你的方法,把颜色放在格式中,而不是把它放在数据中自己

答案 1 :(得分:2)

执行此操作的一种方法是在 printf之后而不是之前应用颜色序列

use strict;
use warnings;
use 5.010;

use Term::ANSIColor;

my $format = '%-10s';

my @greetings = (
    sprintf($format, 'Hello'),
    sprintf($format, 'Greetings')
);

foreach my $greeting (@greetings) {
    say colored($greeting, 'bold red') . ' : ok';
    say "$greeting : ok";
}

输出:

Hello      : ok
Hello      : ok
Greetings  : ok
Greetings  : ok

(第一个Hello和第一个Greetings颜色,当然)

您还可以使用Text::Aligner,它知道如何解释由Term::ANSIColor生成的颜色序列:

use strict;
use warnings;
use 5.010;

use Term::ANSIColor;
use Text::Aligner qw(align);

my @greetings = qw(Hello Greetings);

my @lines;
foreach my $greeting (@greetings) {
    push @lines, colored($greeting, 'bold red') . ' : ok';
    push @lines, "$greeting : ok";
}

say for align(qr/:/, @lines);

输出:

    Hello : ok
    Hello : ok
Greetings : ok
Greetings : ok

(同样,第一个Hello和第一个Greetings颜色)

请注意,这会对冒号中的所有内容进行对齐,因此您不会获得所要求的左对齐输出,但这是另一种思考方式。