Thanks Ken,
Your solution is a lot like what I've come up with but I've taken it a bit further. I checked out the modules Anonymous suggested. String::Interpolate::RE served as the inspiration for my solution.
My solution handles \\\w escapes, \\\w{\w+} and ${\w+} interpolation now where ${\w+} is simply checked against %ENV for a value.
The hash keys include the backslash in the case of \\\w and \\\w{\w+} and the values can be either scalars or coderefs.
I have included the $opts hashref but have not implemented it yet. I will in my final project probably use $opts much like String::Interpolate::RE.
#!/usr/bin/perl
use strict;
use Cwd;
use POSIX;
use Sys::Hostname;
use File::Basename;
sub interpolate {
# heavily borrowed from http://search.cpan.org/~djerius/String-Inter
+polate-RE-0.03/lib/String/Interpolate/RE.pm
my ($string, $repls, $opts) = (@_);
$string =~ s{
(
(?:(\\.)(?:\{([^\}]+)\})?)|
(?:\${(\w+)})
)
}{
my $v;
my $t = (defined($2)) ? $2 : $4;
if (exists($repls->{$t})) {
$v = ref($repls->{$t}) eq 'CODE' ? &{$repls->{$t}}($t,$3) : $rep
+ls->{$t}
} elsif (exists($ENV{$t})) {
$v = $ENV{$t}
}
defined($v) ? $v : $1
}egx;
return $string;
}
my $string = '\s\n\u@\h \w \D{%F}\n\t\n\T\n\@\n\A\n\$\n${LANG}\n\q\n${
+FOO} $ ';
my %repls = (
'\a' => "\a",
'\D' => sub { strftime($_[1], localtime) },
'\e' => "\029",
'\h' => sub { (split(/\./,hostname()))[0] },
'\H' => sub { hostname() },
'\n' => "\n",
'\r' => "\r",
'\s' => sub { basename($0) },
'\t' => sub { strftime('%T', localtime) },
'\T' => sub { strftime('%I:%M:%S', localtime) },
'\A' => sub { strftime('%R', localtime) },
'\@' => sub { strftime('%I:%M %p', localtime) },
'\u' => sub { getpwuid($>) },
'\w' => sub { $_ = cwd(); s/$ENV{HOME}/~/ ; return $_; },
'\W' => sub { (cwd() eq $ENV{HOME}) ? '~' : basename(cwd()) },
'\$' => $>,
);
print interpolate($string,\%repls) . "\n";
Gives:
alan@host ~/test/prompt 2013-04-11
19:43:45
07:43:45
07:43 PM
19:43
500
en_US.utf8
\q
${FOO} $ '
Adding and removing escapes is a matter of adding or removing keys from the hash. Which is good because I am writing a shell framework. (Yes I know about Term::Shell and others but they weren't quite what I want.) But I can include the sort of standard escapes with the Shell and then with my specific implementation of it I can add more...
Thanks Ken, thanks Monks.
-Alan |