Article 7359 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:7359
Newsgroups: comp.lang.perl
Path: feenix.metronet.com!news.utdallas.edu!hermes.chpc.utexas.edu!cs.utexas.edu!uunet!boulder!wraeththu.cs.colorado.edu!tchrist
From: Tom Christiansen <[email protected]>
Subject: Re: Expanding a string with non-printing characters
Message-ID: <[email protected]>
Originator: [email protected]
Sender: [email protected] (USENET News System)
Reply-To: [email protected] (Tom Christiansen)
Organization: University of Colorado, Boulder
References: <[email protected]>
Date: Thu, 28 Oct 1993 10:51:27 GMT
Lines: 121

:-> In comp.lang.perl, [email protected] writes:
:I can't think of a graceful way of doing this.  (I can think of
:several yucky ways.) I know there shoule be a one or two line
:solution.  It's a common problem:
:
:I have a variable, $foo, which may contain any number of control
:characters.  I want to expand the control characters to their
:string representation: "^A" for control-A, "^[" for ESC, and
:so forth.
:
:Suggestions? Places in TFM to R? Send me mail and I will summarize
:if interest warrants.

Well, you could do this:

   s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;

Or you could get fancy:

#!/bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by  on Thu Oct 28 04:49:31 MDT 1993
# Contents:  pit

echo x - pit
sed 's/^@//' > "pit" <<'@//E*O*F pit//'
#!/usr/bin/perl

$debug = 0;
&init;
while (<>) {
   print "line is: ", &printable($_), "\n";
   print "\$_ = '", &evalable($_), "'\n";
}
exit;

###############

sub printable {
   local($_) = @_;
   $_ = &xlate($_,0);
}

sub evalable {
   $_ = &xlate($_,1);
}

###############
sub init {

$code = <<'EOF';
   sub xlate {
       local($_, $evalit) = @_;
       if ($evalit) {
           s/(['\\])/\\$1/g;
           s/([\200-\377])/sprintf("\\%03o",ord($1))/eg;
       } else {
           s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
       }
EOF
$spec_code = "\n";

while (<DATA>) {
   ($char, $xlate, $comment) = split(' ', $_, 3);
   #$char = eval q("$char") if $char =~ /\\/;
   $xlate =~ s/\\/\\\\/;
   $special .= $char;
   $spec_code .= <<"EOF";
           s/$char/$xlate/g;
EOF
}

$code .= <<EOF;
       if (/[$special]/) {
           $spec_code
       }
EOF
$code .= <<'EOF';
       s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
EOF
$code .= <<'EOF';
       return $_;
   }
EOF

print $code if $debug;
eval $code;
if ($@) {
   ($line) = $@ =~ /line\s*(\d+)/;
   die unless $line;
   @lines = split("\n", $code);
   warn "$0: error in compilation:\n\t$@\n";
   for $i ( ($line - 2) .. $line) {
       printf "%3s %2d: %s\n",
           ($i+1 == $line) ? "==>" : '',
           $i+1, $lines[$i];
   }
   die "\n$0: Cannot compile printable functions\n";
}

}

__END__
\0      \0      null
\t      \t      tab
\n      \n      newline
\r      \r      return
\f      \f      formfeed
\010    \b      backspace
\a      \a      bell
\e      \e      escape
@//E*O*F pit//
chmod u=rwx,g=rwx,o=rx pit

exit 0
--
   Tom Christiansen      [email protected]
     "Will Hack Perl for Fine Food and Fun"
       Boulder Colorado  303-444-3212