CocoRuby
CocoRuby

Reputation: 57

Perl - how to get values of tokens

I am searching how to get tokens values in properties file with Perl.

Given the source property:

my $source="application.1.hostname={{DNS_APP}}:{{PORT_APP}}/WHATEVER";

And given the target property:

my $target="application.1.hostname=test.test.com:8080/WHATEVER";

I would like to get the following result:

{{DNS_APP}}=test.test.com
{{PORT_APP}}=8080

I have no trouble to get the tokens with :

my @matches= ( $source =~ /({{.*?}})/g );

But then, how to match with their values ? Is there an easy way, with perl regexps to get these substitutions ?

Another difficulty (but they are execption, so it is not a big deal if this problem is not addressed) is that, sometimes, $target can be

my $target="application.1.hostname=test.test.com/WHATEVER";

Or

my $target="application.1.hostname=test.test.com:8080/SOMETHINGELSE";

Or even

my $target="application.1.hostname=test.test.com/SOMETHINGELSE";

How to deal with that ?

I thank you in advance for you answers.

Regards.

Upvotes: 0

Views: 262

Answers (1)

Sobrique
Sobrique

Reputation: 53488

OK, at a basic level, you can turn your thing into a named capture for a regex. There's a caveat though - you might need to restrict character sets.

But something like this might work:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my $source = "application.1.hostname={{DNS_APP}}:{{PORT_APP}}/WHATEVER";
my $target = "application.1.hostname=test.test.com:8080/WHATEVER";

$source =~ s|\Q{{\E(\w+)\Q}}\E|(?<$1>.*)|g;
$source = qr/$source/; 
print "Using Regex:", $source,"\n";
$target =~ m/$source/;

#%+ is the special named-capture hash. You can access $+{DNS_APP} for example
print Dumper \%+;

Note though - that .* is a greedy match, and that will mean without delimitors/anchors between patterns, this will break. You could perhaps define a more narrow character class - I would think \w normally, but you also have . so perhaps [\w.]+ - or maybe even .*? for non greedy matching instead. This depends rather on what would 'fit' with the types of patterns you're trying to match. If you need to do so with arbitrary patterns, I think you're going to need to need ... something like regex to define the match criteria in the first place.

If your 'targets' are purely that pattern - e.g. trailing static words - you can trim you initial pattern with s/\w+$// which will reduce it to:

application.1.hostname={{DNS_APP}}:{{PORT_APP}}/

Which you then regex transform to:

(?^:application.1.hostname=(?<DNS_APP>.*):(?<PORT_APP>.*)/)

And then get %+ of:

$VAR1 = {
          'DNS_APP' => 'test.test.com',
          'PORT_APP' => '8080'
        };

As you're on 5.8.8 - my first advice is upgrade it, because it's 7 year old software, and is long since end of life.

This variable was added in Perl v5.10.0.

However you should be able to work around by:

my @match_names = $source =~ m|\Q{{\E(\w+)\Q}}\E|g;  #capture 'names' of matches
$source =~ s|\Q{{\E(\w+)\Q}}\E|(.*)|g;
$source = qr/$source/;
print "Using Regex:", $source, "\n";
my %results;
my @matches = $target =~ m/$source/;
@results{@match_names} = @matches;

print Dumper \%results;

I'm pretty sure there's a way of capturing what matched from the s pattern replacement. If I figure out what it was, I'll update.

(As it stands:

my ( @match_names ) =  $source =~ s|\Q{{\E(\w+)\Q}}\E|\(.*\)|g;  

doesn't seem to work as I want - @match_names contains the number of replacements. )

Upvotes: 1

Related Questions