Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a text file that is formatted like this:

color1=\\033[0;30m color2=\\033[0;31m

I need to read these into variables and use them with perls print statements. Perl works fine when you do:
print "\033[0;31m Color Changed";

Obviously if I use it as "\\033[0;31m" it won't work. So i'm removing the first slash and dropping it in a variable.

that much is working, cause if i print the variable I can see it as "\033[0;31m". Problem is that I can see it, it isn't adjusting the color in the terminal.

Any idea on how to bring the values in, and use them to adjust the terminal color?

Replies are listed 'Best First'.
Re: ascii colors from text file
by almut (Canon) on Mar 02, 2007 at 17:49 UTC

    You probably need to eval your string (if I'm understanding your problem correctly) - e.g.

    my $s = '\\033[0;31m' . 'some text' . '\\033[0;31m'; $s = eval qq("$s"); print $s;
      Of course, if he parses the file by splitting on white space and then on "=" like most people would first think to do, then you've ensured that anyone who can edit the color file can cause him to run arbitrary code.

      Maybe not a big deal for him but probably not a great meme to spread around.

      Worse, your example evals the final string, not the color text once when parsing. That means if he has "$1 dollar" anywhere in his text he's getting lord knows what in place of "$1"... probably "=" or the last title word ("color15"?) depending on how his parser works. Hopefully he won't print a nice "$$$$$$$$$$$$" anywhere when decorating his report. :)

      --
      $you = new YOU;
      honk() if $you->love(perl)

        Yeah sure, I agree that eval is always potentially dangerous... I figured this is rather well-known. And, I wasn't trying to spread "great memes" :)   Rather, I was simply trying to generically answer the problem of "Normally, I would use a double quoted string in my script... now what do I do to arrive at the same effect when I hold the part in between the quotes literally in a string, like when having read it from a file?"   Nowhere in the OP was any mention of other people potentially having control over the input.

        Along similar lines you'd have to warn people every time they interpolate some variable into some command like

        system "convert $imgname.png $imgname.jpg"
        because, if $imgname could potentially come from an insecure source, they might get into trouble inadvertendly running something like

        system "convert ; rm -rf ~/* ;.png ..."

        I'd probably even mention it if the danger is obvious, like someone inexperienced trying to execute code like this in CGI context or some such, but otherwise... should we always warn?

      that did it. thanks.
Re: ascii colors from text file
by ikegami (Patriarch) on Mar 02, 2007 at 17:43 UTC

    Those are ANSI escape sequences. You need an ANSI terminal to see them.

    ...or an emulation. On Windows, adding use Win32::Console::ANSI; to your script will add ANSI support to your console.

      I know they are. My terminal has support. If i just drop the escape into a printer statement it works fine.

      I suspect that they escape is being lost as its read in from the text file and i remove the first slash.
        Sorry, I misread.

        In a double quoted string literal, \033 is replaced with character 33 oct (27 dec, 1B hex) in the resulting string. The following two statememts are equivalent.

        $str = "\033"; # ESC $str = chr(033); # ESC

        You'll have to do this conversion somehow.

        while (<DATA>) { s/\\\\033/\033/g; # \\033 -> ESC print; } __DATA__ \\033[0;30mcolor1 \\033[0;31mcolor2
Re: ascii colors from text file
by johngg (Canon) on Mar 02, 2007 at 23:22 UTC
    Detecting the '\\033' sequence and replacing it with a real Esc seems to work. I store the colours in a hash table for easy access.

    use strict; use warnings; my %colours = map { $_->[0] => map { my $str = $_; $str =~ s{\\\\(\d{3})}{chr(oct $1)}e; $str } $_->[1] } map { chomp; [ split m{=} ] } <DATA>; print qq{Black then$colours{color2} red then$colours{color1} black.\n} +; __END__ color1=\\033[0;30m color2=\\033[0;31m

    I hope this is of use.

    Cheers,

    JohnGG