-1

I do not know how to name even what I want to do, I know it's weird.

I have a script and an external configuration file for this script. I want the user to be able to choose the variables themselves in an accessible form. Its something like template.

Script:

#!/usr/bin/perl -w
use strict;

my ($from, $to);
our $period;

require file.conf

$from = '2017-01-01';
$to   = '2017-04-12';

print $period;

open my $fh, '>>', 'file.txt' or die "Cannot open!";
print $fh join ("\n", $period));
close $fh;

file.conf

$period = "$from \- $to";
1;

Expected output:

2017-01-01 - 2017-04-12

This same output should be in file.txt. This solution is not working, on define $period has undefinied variables $from and $to. I want use this line in different line of code.

Is such an output in some way possible? I emphasize that the idea is to make the solution the most aesthetic and most simple for the user who has no idea what a subroutine, hash or even array is.

F. Grela
  • 61
  • 5
  • 2
    Please explain more about the problem. In which way does the code you have shown not satisfy you? – Yunnosch Apr 11 '18 at 19:12
  • 3
    It sounds like you want templating, e.g., [Template Toolkit](http://template-toolkit.org) – Matt Jacob Apr 11 '18 at 19:27
  • This should be marked as a duplicate of [***How can I use a variable as a variable name in Perl?***](https://stackoverflow.com/questions/1549685/how-can-i-use-a-variable-as-a-variable-name-in-perl) Unfortunately I missed my chance to do it myself. – Borodin Apr 11 '18 at 19:30
  • Yes. I mean templating. Thanks. – F. Grela Apr 11 '18 at 19:31
  • You shouldn't be asking the user to write software: that is your job. *"I want the user to be able to choose the variables themselves in an accessible form"* How can the user possibly know what variable identifiers you have used, so that they can select one? – Borodin Apr 11 '18 at 19:34
  • https://metacpan.org/pod/perlfaq7#How-can-I-use-a-variable-as-a-variable-name – Robert Apr 11 '18 at 19:36
  • @Borodin: another explanation: its choose of columns in generated CSV file – F. Grela Apr 11 '18 at 19:36
  • If you move `require file.conf` to *after* the definitions of `$from` and `$to` then your code should do as you ask. But your question is far from clear, and it isn't obvious what sorts of things you want to be able to do in general. – Borodin Apr 11 '18 at 19:42

2 Answers2

5

You are trying to create a template system. Instead, use an existing one.

use Template qw( );

my $from = '2017-01-01';
my $to   = '2017-04-12';

# Name of a file or reference to string containing the template.
my $template = \ "[% from %] - [% to %]";

my $vars = {
   from => $from,
   to   => $to,
};

my $tt = Template->new({ });
$tt->process($template, $vars)
   or die($tt->error());
ikegami
  • 367,544
  • 15
  • 269
  • 518
0

First, I fully second ikegami's answer - it sounds like you're looking for a templating system like Template::Toolkit. While its syntax isn't exactly Perl, from what you write it sounds like your users aren't programmers, so templates like these might be better than giving them the full power of an entire programing language.

Having said that, for the sake of completeness, the way to get your original code working is with eval, since then, as opposed to do/require, the executed code will be able to see the lexicals $from and $to. As always, this comes with the warning that running this on user-supplied input can be dangerous since it allows the execution of arbitrary code. This produces your expected output:

use warnings;
use strict;

my $templ = do { open my $fh, '<', 'file.conf' or die $!; local $/; <$fh> };

my $from = '2017-01-01';
my $to   = '2017-04-12';
our $period;

eval "$templ; 1" or die $@;

print $period, "\n";
haukex
  • 2,973
  • 9
  • 21