I agree with hippo that this seems to be moving into XY Problem territory. What about /a/b/c/\$USER? Or /a/b/c/\\$USER? Or malformed inputs like /a/b/c/${USER? And what other possible inputs haven't you told us about?

Enough rope to shoot yourself in the foot:

use warnings; use strict; sub interpolate { local $_ = shift; my $vars = shift; my @out; pos=undef; while (1) { if ( m{\G ( [^\\\$]+ ) }xmsgc ) { push @out, $1 } elsif ( m{\G \$ (?| (\w+) | \{(\w+)\} ) }xmsgc ) { push @out, $vars->{$1} } elsif ( m{\G \\ (.) }xmsgc ) { $1 eq "\\" or $1 eq "\$" or die "unexpected backslash escape"; push @out, $1; } else { last } } die "parse of '$_' failed at pos ".(pos//0) if !defined pos || pos!=length; return join '', @out; } use Test::More; sub exception (&) { eval { shift->(); 1 } ? undef : ($@ || die) } my %env = ( USER => "foobar", quz => "\$baz \\\\ \\\$" ); is interpolate("USER", \%env), "USER"; like exception { interpolate("\\USER"), \%env }, qr/\bunexpected backslash\b/; is interpolate("\\\\USER", \%env), "\\USER"; is interpolate("\$USER", \%env), "foobar"; is interpolate("\${USER}", \%env), "foobar"; is interpolate("\\\$USER", \%env), "\$USER"; is interpolate("\\\\\$USER", \%env), "\\foobar"; is interpolate("\\\\\\\$USER", \%env), "\\\$USER"; is interpolate("\\\\\\\\\$USER", \%env), "\\\\foobar"; is interpolate("\\\\\\\\\${USER}", \%env), "\\\\foobar"; is interpolate("\$quz", \%env), "\$baz \\\\ \\\$"; like exception { interpolate("USER\$"), \%env }, qr/\bparse of 'USER\$' failed\b/; like exception { interpolate("\${USER"), \%env }, qr/\bparse of '\$\{USER' failed\b/; done_testing;

I wouldn't necessarily recommend doing much more (e.g. String::Interpolate), as otherwise you may end up opening a security hole.

Update: I realized that the code I posted originally (below) would also unescape backslashes and $s in the values of variables interpolated into the string, so I rewrote the parser using m/\G/gc regexes above. It should now also be more roboust in the face of invalid inputs. The only minor downside is that now integrating String::Unescape isn't quite as easy.

Original code:

use warnings; use strict; use Test::More; sub exception (&) { eval { shift->(); 1 } ? undef : ($@ || die) } my %_interp_map = ( '\\'=>'\\', '$'=>'$' ); # or use String::Unescape sub interpolate { my $str = shift; $str =~ s{ (?<!\\) ((?:\\\\)*) \$ (?| (\w+) | \{(\w+)\} ) } { $1.$ENV{$2} }xeg; $str =~ s{ \\ (.) } { $_interp_map{$1} || die "unexpected backslash escape" }xeg; return $str; } local $ENV{USER} = "foobar"; is interpolate("USER"), "USER"; like exception { interpolate("\\USER") }, qr/unexpected backslash/i; is interpolate("\\\\USER"), "\\USER"; is interpolate("\$USER"), "foobar"; is interpolate("\${USER}"), "foobar"; is interpolate("\\\$USER"), "\$USER"; is interpolate("\\\\\$USER"), "\\foobar"; is interpolate("\\\\\\\$USER"), "\\\$USER"; is interpolate("\\\\\\\\\$USER"), "\\\\foobar"; is interpolate("\\\\\\\\\${USER}"), "\\\\foobar"; done_testing;

In reply to Re: rel2abs of a path with env (updated) by haukex
in thread rel2abs of a path with env by ovedpo15

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.