Perl's Term::ANSIColor is good but sometime it's overkill. I wrote a function to change colors before your print.
$color = color("13_on_5");
$reset = color("reset");
print $color . "Pink on purple" . $reset . "\n";
# or
print color('yellow', "Warning:"); # Print text and reset
The ANSI color numbers can be determined using term-colors.pl.
# String format: '115', '165_bold', '10_on_140', 'reset', 'on_173', 'red', 'white_on_blue'
sub color {
my ($str, $txt) = @_;
if (-t STDOUT == 0 || $ENV{NO_COLOR}) { return $txt // ""; } # No interactive terminal
if (!length($str) || $str eq 'reset') { return "\e[0m"; } # No string = RESET
# Some predefined colors/commands
my %color_map = qw(red 160 blue 27 green 34 yellow 226 orange 214 purple 93 white 15 black 0);
my %cmd_map = qw(bold 1 italic 3 underline 4 blink 5 inverse 7);
# Pre-process the string.
$str =~ s/on_/-/; # "on_" becomes a negative number
$str =~ s|([A-Za-z]+)|$color_map{$1} // $1|eg; # command number
my @parts = split("_", $str);
foreach my $p (@parts) {
my $cmd_num = $cmd_map{$p // 0};
if ($cmd_num) { $p = $cmd_num; }
elsif (defined($p) && $p =~ /^-(.+)/) { $p = "48;5;$p"; }
elsif (defined($p)) { $p = "38;5;$p"; }
}
my $ret = "\e[" . join(";", @parts) . "m";
if (defined($txt)) { $ret .= $txt . "\e[0m"; }
return $ret;
}
Note: You can test if you're outputting to a TTY which supports ANSI colors, or a file using the -t test.
See also: Regexp to check for ANSI color codes
See also: Tests
Tags: