in reply to Strings with undefined variables?

Is anything like this even doable?

Don't know what pabulum Pythonistas are used to, but for Perl we all know the answer to that ...

Anyway, if you are going to use regexes then absolutely make sure that when you set your $url you do use single quotes so that any variable-looking entities in there do not get interpolated. The way you do it in your example $GUID will be interpolated to empty, and because you do not use strict/warnings you will not even know it when it disappears.

Secondly, if you use regexes, your "variables" inside the $url are not necessary to look like perl variable names (e.g. $GUID). You can adopt any convention which makes the regex substitution easy and unambiguous. For example, and I am only trying to make a point by being extreme, you can use my $url = "http://something.com/api_stuff/<<<<VAR:GUID>>>>"; (note: single or double quotes in this case do not matter - there are no "Perl-looking" vars in there).

Of course, it is also possible to use $GUID in $url (as you do) but you have some escaping to do. At least use ${GUID} to decrease ambiguity. But there is absolutely no reason to use the dollar-sign and that brings you back to my suggestion.

For the really specific use-case you provide, I see no reason why you should use a variable like $GUID in your $url and then have it substituted. You could have a base URL which various functions take, along with GUIDs and other params and then they form a valid url by appending etc. That is, each function knows what URL format it has to return inherently, inside the function (and not globally as you do), and does whatever transformations are necessary with whatever input is required in order to produce and return the valid URL.

Of course, there are lots and lots of ways to achieve what you want, this is just one since you mentioned regex.

bw, bliako

Replies are listed 'Best First'.
Re^2: Strings with undefined variables?
by 23skiddoo (Beadle) on Jan 04, 2019 at 12:58 UTC

    Thanks! Yeah, I expected I could do something like the following. Note that the actual use case involves several URLs that would like to store in a hash. (Also, I've been using Perl for almost 20 years, mostly in text processing. Only dabbled in Python and don't care for it much.)

    my %URLS = ( upload => 'https://somewhere.com/api1', process => 'https://somewhere.com/=GUID=/api2', ); my $guid = upload_file( $ARGV[0] ); my $rtn = process_file( $guid ); sub upload_file { my $fn = shift; # LWP::UserAgent stuff my $g = $ua->post( $URLS{ upload } . '?' . $fn ); return $g; } sub process_file { my $guid = shift; # LWP::UserAgent stuff ( my $this_url = $URLS{ process } ) =~ s/=GUID=/$guid/; my $result = $ua->post( $this_url ); return $result || 0; }
    fnord

      That's cool. And if you pass to your subs a hash of substitutions a-la 'GUID'=>123 you will have a very light template system ...

      bw, bliako

        I've done pretty much exactly this on many occasions. Works very well for specifying user visible strings in a separate file and referencing them by ID.

        #! /usr/bin/env perl use strict; use warnings; my %templates = ( url => 'http://something.com/api_stuff/%guid%' ); print format_template( url => guid => 1234 ); sub format_template { my $template_id = shift; my $template = $templates{$template_id}; my (%args) = @_; foreach (keys %args) { $template =~ s/%$_%/$args{$_}/; } return $template; }

        πάντων χρημάτων μέτρον έστιν άνθρωπος.