tags:

views:

105

answers:

4

can we source a shell script in the perl script??

Example: Program 1:

cat test1.sh
#!/bin/ksh
DATE=/bin/date

program 2:

cat test2.sh
#!/bin/ksh
. ./test1.sh  
echo `$DATE`

Program 3:

cat test3.pl
#!/usr/bin/perl
### here I need to source the test1.sh script
print `$DATE`'

How to source the shell in perl to get the date printed when I execute test3.pl

thanks raghu

A: 

You cannot do a

system("source src.sh");

system() starts a new sub-shell, your environment variables do not get passed to the shell your Perl script is running in. Even though your shell script exports variables, it will export them to the sub-shell, not to your actual shell.

One solution would be to write a wrapper script which

  1. First sources the shell script and then
  2. Runs the Perl script
codaddict
This is what I generally do, but it doesn't work if you want to source different files depending what you are doing. For instance, lets say you have three databases and need different environments to access them. You don't know in advance which database you will need to connect to. In cases like that the wrapper method falls down.
Chas. Owens
@Chas. Owens: You are right.
codaddict
A: 

You can't source shell files in Perl 5. Sourcing is literally running the commands in the shell file in the target shell; however, it is trivial to open and read the file:

#!/usr/bin/perl

use strict;
use warnings;

use Carp;

sub source {
    my $file = shift;
    open my $fh, "<", $file
        or croak "could not open $file: $!";

    while (<$fh>) {
        chomp;
        #FIXME: this regex isn't quite good enough
        next unless my ($var, $value) = /\s*(\w+)=([^#]+)/;
        $ENV{$var} = $value;
    }
}

source "./test1.sh";

print "$ENV{DATE}\n";
Chas. Owens
A: 

Uhm.. is the below cheating?

#!/bin/sh
. ./test1.sh # source the test script
echo Bash says $DATE
export DATE;      # KEY to have the below Perl bit see $ENV{DATE}
perl <<'ENDPERL';
    print "Perl says $ENV{DATE}\n";
ENDPERL

The problem is that sourcing the sh file may do whatever, and not just assign value X to variable Y...

mfontani
A: 

I don't know that this will help, but I felt compelled to come up with a way to write this in Perl. My intent was to have Perl run a shell script, and to assign any shell variables it sets to like-named variables in the Perl script.

The others are correct in that any shell script you "source" is going to be in a sub-shell. I figured I could use "sh -x cmd" to at least have the shell show the variables as they're set.

Here's what I wrote:

use strict;  use warnings;

our $DATE;

my $sh_script = "./test1.sh";

my $fh;
open($fh, "sh -x '$sh_script' 2>&1 1>/dev/null |") or die "open: $!";
foreach my $line (<$fh>) {
    my ($name, $val);
    if ($line =~ /^\+ (\w+)='(.+)'$/) {  # Parse "+ DATE='/bin/date;'
        $name = $1;
        ($val = $2) =~ s{'\\''}{'}g;  # handle escaped single-quotes (eg. "+ VAR='one'\''two'")
    } elsif ($line =~ /^\+ (\w+)=(\S+)$/) {  # Parse "+ DATE=/bin/date"
        $name = $1;
        $val = $2;
    } else {
        next;
    }
    print "Setting '$name' to '$val'\n" if (1);
    # NOTE: It'd be better to use something like "$shell_vars{$name} = $val",
    #  but this does what was asked (ie. $DATE = "/bin/date")...
    no strict 'refs';
    ${$name} = $val;    # assign to like-named variable in Perl
}
close($fh) or die "close: ", $! ? $! : "Exit status $?";

print "DATE: ", `$DATE` if defined($DATE);

There's certainly more error-checking you could do, but this did the trick for me if all you want to catch is shell variables.

Michael Krebs