ag4ve has asked for the wisdom of the Perl Monks concerning the following question:
I've got a 'config' file that a shell script sources - I can't change the config file format but need to use the data in perl. Currently, I have a shell script that exports the values and then runs the perl script and just use $ENV{val} from within perl. But this seems clunky. Is there a way of parsing something like this in perl:
A="foo" B="some other data" C="appending $A" D=" some list with more data and $B "
Which with my current implementation, I'd have a shell script:
#!/bin/bash - . foo.conf export A export B export C export D ./foo.pl
And then:
#!/usr/bin/perl my %exp_vars = ( A => 'SCALAR', B => 'SCALAR', C => 'SCALAR', D => 'ARRAY', ); my $env; foreach my $var (keys %exp_vars) { my $type = $exp_vars{$var}; my $val = lc $var; if (! defined $ENV{$var} or length($ENV{$var}) <= 1) { push @out, "# [$var] not exported"; next; } if ($type eq 'ARRAY') { @{$env->{$val}} = ($ENV{$var} =~ m/(?:\s+)?(\S+)/g); } elsif ($type eq 'SCALAR') { $env->{$val} = $ENV{$var}; } }
So, how do I remove the shell script from this?
EDITAfter looking at the messing with Shell::Parser and looking at the suggestions, I took what I needed and came got the below (basically, I didn't see that Shell::Parser was givin me anything, so I parsed out the variables myself and then look any shell values that need to be interpreted:
#!/bin/env perl use strict; use warnings; use Data::Dumper; sub parse_sh { my ($data) = @_; my $r; $data =~ s/((?: *#.*?)?\n+)/\n/gs; # Remove comment lines $data =~ s/(\n+)/\n/gs; # Remove blank lines $data =~ s/ *(\S+)=("?)(.*?)\2 *\n/$r->{lc($1)}="$3"/gse; return $r; } sub parse_sh_maint { my ($r, $noset) = @_; # Interpolate variable names my $max_passes = 5; my $not_substituted; for (1 .. $max_passes ) { for my $k (keys %$r) { next unless (ref(\$r->{$k}) eq 'SCALAR'); $r->{$k} =~ s|\$(\w+)| $r->{lc($1)} // do{ "\$$1" } |ge; $not_substituted += $r->{$k} =~ tr/$/$/; } last unless $not_substituted; } # Remove remaining variables and make variables with spaces and newl +ines arrays for my $k (keys %$r) { $r->{$k} =~ s/\$\S+ *?//gs; # Remove remaining varia +bles $r->{$k} =~ s/\s+/\n/gs; # Remove leading spaces if (not grep { $_ eq $k } @$noset) { my %dedupe = map { $_ => 1 } split(/ |\n/, $r->{$k}); $r->{$k} = (); @{$r->{$k}} = keys %dedupe; } } return $r; } open(my $fh, "<", $ARGV[0]); my $content = do { local $/ = <$fh> }; my $stuff = parse_sh_maint(parse_sh($content), [qw/scalar1 scalar2/]); print "Vars: " . Dumper($stuff), "\n";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Parsing bash data
by Perlbotics (Archbishop) on Aug 23, 2013 at 15:40 UTC | |
by ag4ve (Monk) on Aug 23, 2013 at 17:57 UTC | |
|
Re: Parsing bash data
by choroba (Cardinal) on Aug 23, 2013 at 15:34 UTC | |
|
Re: Parsing bash data
by kcott (Archbishop) on Aug 24, 2013 at 12:33 UTC | |
|
Re: Parsing bash data
by Laurent_R (Canon) on Aug 23, 2013 at 17:48 UTC |