我想从“my_perl.pl”调用“env.sh”而不需要子shell。我尝试了这样的背景和系统 - > system (. env.sh)
[点空间env.sh]然而不会工作。
答案 0 :(得分:14)
子环境无法更改父环境。最好的办法是从Perl代码中解析env.sh
并在%ENV
中设置变量:
#!/usr/bin/perl
use strict;
use warnings;
sub source {
my $name = shift;
open my $fh, "<", $name
or die "could not open $name: $!";
while (<$fh>) {
chomp;
my ($k, $v) = split /=/, $_, 2;
$v =~ s/^(['"])(.*)\1/$2/; #' fix highlighter
$v =~ s/\$([a-zA-Z]\w*)/$ENV{$1}/g;
$v =~ s/`(.*?)`/`$1`/ge; #dangerous
$ENV{$k} = $v;
}
}
source "env.sh";
for my $k (qw/foo bar baz quux/) {
print "$k => $ENV{$k}\n";
}
鉴于
foo=5
bar=10
baz="$foo$bar"
quux=`date +%Y%m%d`
打印
foo => 5
bar => 10
baz => 510
quux => 20110726
代码只能处理简单文件(例如,它不处理if
语句或foo=$(date)
)。如果你需要更复杂的东西,那么首先为你的Perl脚本编写一个包装器env.sh
是正确的方法(它也可能是最好的方法)。
在执行Perl脚本之前获取env.sh
的另一个原因是在Perl中设置环境变量可能对于期望看到它们的模块来说太晚了。
在文件foo
中:
#!/bin/bash
source env.sh
exec foo.real
其中foo.real是你的Perl脚本。
答案 1 :(得分:2)
您可以使用任意复杂的shell脚本,通过相关shell执行它们,将它们的环境转储到同一进程中的标准输出,并在perl中解析它。将输出提供给%ENV以外的其他内容或过滤特定的感兴趣值是谨慎的,因此您不会改变PATH之类的其他地方可能会产生有趣副作用的事情。我已经从生成的shell脚本中丢弃了标准输出和错误,尽管它们可以重定向到临时文件并用于perl脚本中的诊断输出。
foo.pl:
#!/usr/bin/perl
open SOURCE, "bash -c '. foo.sh >& /dev/null; env'|" or
die "Can't fork: $!";
while(<SOURCE>) {
if (/^(BAR|BAZ)=(.*)/) {
$ENV{$1} = ${2} ;
}
}
close SOURCE;
print $ENV{'BAR'} . "\n";
foo.sh: 出口BAR = baz
答案 2 :(得分:2)
试试这个(unix代码示例):
cd / tmp
vi s
#!/bin/bash
export blah=test
vi t
#!/usr/bin/perl
if ($ARGV[0]) {
print "ENV second call is : $ENV{blah}\n";
} else {
print "ENV first call is : $ENV{blah}\n";
exec(". /tmp/s; /tmp/t 1");
}
chmod 777 s t
./吨
ENV首先打电话是:ENV第二次调用是:test
诀窍是首先使用exec来源你的bash脚本然后再用一个参数调用你的perl脚本,这样你就知道你第二次被调用了。