Chaoui05 has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks !! I don't know if following question is a simple issue but i ask it anyway.

I would like to recover a path ("my $folder") from below conf.file using perl:

my $folder = 'E:\FOLDER\Test\WEB'; { license => 'kit-licence.zip', programs => [ #template society =>\%program_work 'VIKTOR DESCRIPTION PRODUCT' => { name => 'VIKTOR ', parameters => [ Count_id => '06 ( +Viktor)', Birth_date => '1995-04-3 +0', Marriage_date => '2014-05-26', Divorce_date => '2015-03-30', Activities_folder => $folder. +'\VIKTOR\independent worker', Activities_format => 'Enterpr +ise Format (V35)', Description_File_from => $folder.'\VI +KTOR\FILE\description.xml', ] }, ] };

And i would like to add (logically at the end of path) in this path,the filename: 'kit-licence.zip' from here : license => 'kit-licence.zip'

My perl file is following :

#test.pl use Modern::Perl; my $config = do 'work.conf'; use Data::Dumper; say Dumper( $config );

How can i do it ?

Many thanks !!

*****Lost in translation****TIMTOWTOI****Soon a monk but not yet****

Replies are listed 'Best First'.
Re: Recover a path from a config file
by haukex (Archbishop) on Jun 06, 2016 at 10:51 UTC

    Hi Chaoui05,

    Because the $folder variable is declared with my, it exists only for the scope of the config file and is not accessible from the main script. One quick solution would be to replace the "my" with an "our" in the config file, as that declares the variable as a package ("global") variable, then add a declaration of "our $folder;" (or "use vars qw/$folder/;", but that's discouraged) before the line with do 'work.conf' (this is to satisfy strict), then the variable $folder will be accessible in the script, and then you can do:

    use File::Spec::Functions qw/catfile/; my $filename = catfile($folder, $config->{license});

    Hope this helps,
    -- Hauke D

    Edit: Minor updates to wording.

      Hey haukex . Thanks for reply.

      Global variable is a good idea ! I tried it but i get an issue. Here my output :
      Global symbol "$folder" requires explicit package name at...line44

      Thanks in advance !

      *****Lost in translation****TIMTOWTOI****
Re: Recover a path from a config file
by Corion (Patriarch) on Jun 06, 2016 at 11:39 UTC

    Personally, I would make $folder part of the config structure:

    my $folder = 'some/where/else'; { my $folder = 'E:\FOLDER\Test\WEB'; { source_folder => $folder, license => 'kit-licence.zip', programs => [ #template society =>\%program_work 'VIKTOR DESCRIPTION PRODUCT' => { name => 'VIKTOR ', parameters => [ Count_id => '06 ( +Viktor)', Birth_date => '1995-04-3 +0', Marriage_date => '2014-05-26', Divorce_date => '2015-03-30', Activities_folder => $folder. +'\VIKTOR\independent worker', Activities_format => 'Enterpr +ise Format (V35)', Description_File_from => $folder.'\VI +KTOR\FILE\description.xlm', ] }, ] }; };

      Hello Corion. Thanks for reply

      I thought about your approach but i cannot modify my config.file

      So i have to do differently.

      *****Lost in translation****TIMTOWTOI****

        Hi Chaoui05,

        i cannot modify my config.file

        With Perl you can ;-)

        There are several other ways to solve this (maybe even PadWalker), and personally I think the following is a hack that's not very nice, but it works as long as your config file only contains one declaration of my $folder...

        my $conf_str = do { open my $fh, '<', 'work.conf' or die $!; local $/; <$fh> }; # slurp ( $conf_str =~ s/\bmy\s*\$folder\b/our \$folder/g )==1 or die q{Failed to match "my $folder" exactly once}; our $folder; my $config = eval $conf_str;

        Hope this helps,
        -- Hauke D

        If you cannot modify the config file, then none of the suggestions here will help. Perhaps you could use eval instead of do?

        use strict; use warnings; use Data::Dumper; my ($content); { open my $fh,'<','work.conf' or die $!; local $/; $content = <$fh>; } my $config = eval $content; print Dumper(\$config);
        But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

Re: Recover a path from a config file
by BrowserUk (Patriarch) on Jun 06, 2016 at 11:48 UTC

    If you create the variable in the config as $::folder = 'E:\FOLDER\Test\WEB';, then it is available in the main program in the same way.

    However, the bulk of the config will be inaccessible as it is declared as an anonymous hash with no name.

    You could fix that with work.conf:

    $::folder = 'E:\FOLDER\Test\WEB'; $::config = { license => 'kit-licence.zip', programs => [ #template society =>\%program_work 'VIKTOR DESCRIPTION PRODUCT' => { name => 'VIKTOR ', parameters => [ Count_id => '06 ( +Viktor)', Birth_date => '1995-04-3 +0', Marriage_date => '2014-05-26', Divorce_date => '2015-03-30', Activities_folder => $folder. +'\VIKTOR\independent worker', Activities_format => 'Enterpr +ise Format (V35)', Description_File_from => $folder.'\VI +KTOR\FILE\description.xlm', ] }, ] };

    Main program:

    #! perl -slw use strict; use Data::Dump qw [ pp ]; do 'work.conf' or die $!; print $::folder; pp $::config;

    Output:

    C:\test>junk Name "main::folder" used only once: possible typo at C:\test\junk.pl l +ine 7. Name "main::config" used only once: possible typo at C:\test\junk.pl l +ine 9. E:\FOLDER\Test\WEB { license => "kit-licence.zip", programs => [ "VIKTOR DESCRIPTION PRODUCT", { name => "VIKTOR ", parameters => [ "Count_id", "06 (Viktor)", "Birth_date", 1995-04-30, "Marriage_date", 2014-05-26, "Divorce_date", 2015-03-30, "Activities_folder", "E:\\FOLDER\\Test\\WEB\\VIKTOR\\independent wo +rker", "Activities_format", "Enterprise Format (V35)", "Description_File_from", "E:\\FOLDER\\Test\\WEB\\VIKTOR\\FILE\\descript +ion.xlm", ], }, ], }

    Also $main::config & $main::folder would work. Or you could go the OO route and make work.conf a proper object.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.

      Hello . Thanks for reply.

      In fact, i just want to get my path + filename in my test.pl using perl, knowing i have to keep my config.file unchanged.

      Thanks in advance !

      *****Lost in translation****TIMTOWTOI****
Re: Recover a path from a config file
by RonW (Parson) on Jun 06, 2016 at 19:27 UTC

    Using do or eval to parse files like your work.conf is potentially very dangerous. Arbitrary Perl code can be inserted in files like that.

    I have used Data::Undump with some success to more safely read data from files like your work.conf

    However, since you are interested in only the values for $folder and license, you could extract those with regular expressions

    (Untested)

    use strict; use warnings; my $dir; my $lic; my $cfgf = 'work.conf'; open my $cfgh, '<', $cfgf or die "Can't open $cfgf: $!\n"; while (<$cfgh>) { if (/\$folder\s+=\s+'([^']+)'/) $dir = $1; next; } if (/license\s+=>\s+'([^']+)'/) { $lic = $dir . $1; last; } } print "Folder: $dir\nLicense: $lic\n";

      Hello ,

      Thanks for your approach. It's a very interesting to use regex . I didn't think about that even if i have to learn more about them.

      Concerning do i use, i have to employ that to read my file.

      I didn't know it can be dangerous to use do or  eval. The advantage of my conf.file is the format because it uses Perl.

      *****Lost in translation****TIMTOWTOI****

        The advantage of my conf.file is the format because it uses Perl.

        Think of it like a perl program, because it is a perl program, use/require/do/eval, they all run perl programs like "perl"

        The assumptions/conventions are different, but its full perl interpreter, unrestrained

Re: Recover a path from a config file
by anonymized user 468275 (Curate) on Jun 06, 2016 at 19:24 UTC
    Strangely I didn't see this at the beginning of the evening, but after four glasses of wine, I suddenly thought of this and began to wonder why not only me but noone else thought of it yet. I do NOT claim it's subtle coding ;)
    open my $ch, 'path to config file'; my $folder; my $assignment = <$ch>; close $ch; chomp $assignment; $assignment =~ s/^\s*my\s*//; eval $assignment; # assigns to THIS scope!

    One world, one people

        I don't want to get into that example in too much detail as it serves no proper purpose. However, I do have issues with it, for example the local $/ doesn't assign anything so doesn't do anything. Meanwhile I have been thinking what would a proper solution be and I keep getting back to the fact that this is not the best way write a config file. Better would be to have
        { folder => 'path',
        in the following hash, instead of
        my $folder = 'path';
        In any case, unless the config file is used to load all configuration data rather than pick just one item, then it is being misused as well as ill-conceived. There are two types of config file. The language portable one that is just a list of identifiers followed by their values and the "normal" perl way: a class-qualified symbol and a hash assigned to it, which is intended to be loaded in easily enough using just one "require" statement.

        Unfortunately, the OP seems to be suffering from an organisation culture that stubbornly resists change even to fix bad implementations. In the wider Perl community we know who they are by reputation and simply avoid working there!

        One world, one people

        Yes. exact
        *****Lost in translation****TIMTOWTOI****
Re: Recover a path from a config file
by Chaoui05 (Scribe) on Jun 06, 2016 at 15:51 UTC

    I did that now and it works:

    In my folder, in config.file

    $::folder = 'E:\FOLDER\Test\WEB';
    And in my test.file :
    use File::Spec::Functions qw/catfile/; my $filename = catfile($::folder, $config->{licence});

    And it works fine.

    Thanks all

    PS: I have now my config.file with thoses little changes, at the beginning of this one :

    my $folder = 'E:\FOLDER\Test\WEB'; { license => [ 'kit-licence.zip', 'kit-work.zip' ], programs => [..

    I have this simple question. How can i do if i want to get first licence or the second doing that :

    use File::Spec::Functions qw/catfile/; my $filename = catfile($::folder, $config->{licence});

    Thanks

    *****Lost in translation****TIMTOWTOI****
      use strict; use warnings; #use Data::Dumper; my ($content); { open my $fh,'<','work.conf' or die $!; local $/; $content = <$fh>; } my $config = eval $content; #print Dumper(\$config); print 'Licences: ' . join ',', @{$config->{licence}};

      Update: to look at the first and second specifically, try the following.

      printf "First licence: %s\n", ${$config->{licence}}[0]; printf "Second licence: %s\n", ${$config->{licence}}[1];

      Updated again: if the contents of the licence tag could be either a single value or a list of values, you will need to use the ref command to tell the difference.

      use File::Spec::Functions qw/catfile/; ... if (ref($config->{licence}) eq 'ARRAY') { foreach my $lfile (@{$config->{licence}}) { print catfile($::folder,$lfile) } } else { print catfile($::folder,$config->{licence}) }
      But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

        Hey GotToBTru,

        Thanks for reply!! Your approach is pretty good. I would like to have same level in "Hash".

        Condition is very useful in this particular cas namely when tag can be either a single value or a list.

        *****Lost in translation****TIMTOWTOI****
Re: Recover a path from a config file
by Chaoui05 (Scribe) on Jun 06, 2016 at 13:27 UTC

    Maybe i didn't ask clear enough my question. I don't want to recover all my config.file. I can do it. I just want to recover path "my $folder" . And add just after licence filename.

    I'am doing some tests and i would like to get from my config.file this path using Perl.

    And use ,after that, this file to do my tests. Knowing i have to keep my config.file almost identical. For example, i can change "my" to "our" to get a global variable cause it's a very small change.

    Global variable seems to be a good approach but i have above issue as i told before.

    HTH

    Many thanks again !!

    *****Lost in translation****TIMTOWTOI****Almost a monk***
      I am confused about this "I can change some stuff, but not much stuff" requirement?

      The code from BrowserUk works fine for me. To eliminate the "only used once" warnings, just declare $folder in main:: as an "our" variable. An "our" variable gets into the global symbol table and can be accessed by anybody with the full name without any import/export adieu. Here is a modified main program...

      #! perl -slw use strict; use Data::Dump qw [ pp ]; our $folder; #to prevent "only used once" warnings our $config; do 'work.conf' or die $!; print $folder; # $folder is declared above, here in $main # not in file work.conf # since we are in main, don't need "full name" pp $::config; #can use full name here, but not necessary
      work.conf as posted by browserUk:
      $::folder = 'E:\FOLDER\Test\WEB'; $::config = { license => 'kit-licence.zip', programs => [ #template society =>\%program_work 'VIKTOR DESCRIPTION PRODUCT' => { name => 'VIKTOR ', parameters => [ Count_id => '06 (Viktor)', Birth_date => '1995-04-30', Marriage_date => '2014-05-26', Divorce_date => '2015-03-30', Activities_folder => $folder.'\VIKTOR\i +ndependent worker', Activities_format => 'Enterprise Format + (V35)', Description_File_from => $folder.'\VIKTOR\F +ILE\description.xlm', ] }, ] };
      works fine. Why isn't this good enough?

      As an update, This back slash stuff for file names under Windows is not required. Use the forward slash. That is easier, more portable and completely allowed since I think at least Win98. The modern Window's command line is NOT DOS.

        Hi Marshall. You right.

        I finally can use a part of browserUk code in mine. A very small part. And i will use a part of haukex code too. I will explain it after.

        *****Lost in translation****TIMTOWTOI****

      Hi Chaoui05,

      For example, i can change "my" to "our" to get a global variable cause it's a very small change.

      But earlier you said:

      I meant i have to not modify my config.file. I have to keep it unchanged.

      ... so if you can edit your config file, and if by "above issue" you mean this, then have a look again at my post, I'm guessing you missed the our $folder; in your main script.

      Hope this helps,
      -- Hauke D

        Yes excuse me. I was too much affirmative. Much for me.

        I can do some little changes , which do not lead to a significant impact on config.file structure. I meant.

        In all cases, thanks again haukex. And yes i will review that .

        *****Lost in translation****TIMTOWTOI****
Re: Recover a path from a config file
by Chaoui05 (Scribe) on Jun 07, 2016 at 13:29 UTC

    Hey monks !

    I request your wisdom last time for this subjet. I would prefer to post it here than to edit it in a new post.

    I would like to get value below :

    name => 'VIKTOR ',

    And i did that :

    my $firstName = $config->{name};

    And i tried following code too but it doesn't work too:

    my $firstName = ${$config->{programs}}[0];

    It doesn't work . I would like to understand. Did i forget something?

    Thanks !!

    *****Lost in translation****TIMTOWTOI****Scribe !yes!***
      It doesn't work . I would like to understand. Did i forget something?

      Just these:

      • A detailed specification of the way in which it "doesn't work"
      • The precise, full text of the error message you received
      • An SSCCE demonstrating the problem in a reproducible manner

      Without these the problem could simply be a typo in your code and nobody would ever know. Help others to help you.

        Yes . Much for me. I forgot output:

        When i do :

        my $firstName = $config->{name};

        I get the following output :

        Use of uninitialized value $firstName in print atline 115.

        And when i do that :

        my $firstName = ${$config->{programs}}[1];

        i get output below :

        HASH(0x3e25178)

        If i do :

        my $firstName = ${$config->{programs}}[0];

        i obtain in my output:

        VIKTOR DESCRIPTION PRODUCT
        *****Lost in translation****TIMTOWTOI****