如何在perl脚本中获取shell脚本[环境变量]而不需要子shell?

时间:2011-07-26 11:16:02

标签: perl shell

我想从“my_perl.pl”调用“env.sh”而不需要子shell。我尝试了这样的背景和系统 - > system (. env.sh) [点空间env.sh]然而不会工作。

3 个答案:

答案 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脚本,这样你就知道你第二次被调用了。