可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
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
- First sources the shell script and then
- Runs the Perl script
回答2:
You can do something simple, like this:
system "source /path/to/shell_env.sh &&" . "/path/to/script.sh";
NOTE that this is different than the following which is not recommended:
system "source /path/to/shell_env.sh &&" . "/bin/sh /path/to/script.sh";
回答3:
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";
回答4:
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...
回答5:
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.
回答6:
Yes, you can now do this with the Env::Modify
module.
use Env::Modify qw(:ksh source); source("./test1.sh"); # env settings from test1.sh now available in Perl print `$ENV{DATE}`; # print `/bin/date`;