我们可以在perl脚本中获取shell脚本吗?

时间:2010-09-09 10:16:33

标签: perl

我们可以在perl脚本中找到一个shell脚本吗?

实施例: 计划1:

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

计划2:

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

计划3:

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

如何在perl中获取shell以获取执行test3.pl

时打印的日期

感谢 raghu

7 个答案:

答案 0 :(得分:4)

你无法做到

system("source src.sh");

system()启动一个新的子shell,你的环境变量不会传递给运行Perl脚本的shell。即使你的shell脚本导出变量,它也会将它们导出到子shell,不是你的实际外壳。

一种解决方案是编写一个包装脚本

  1. 首先来源shell脚本然后
  2. 运行Perl脚本

答案 1 :(得分:1)

你可以做一些简单的事情,比如:

system "source /path/to/shell_env.sh &&"
     . "/path/to/script.sh";

请注意,这与以下建议不同:

   system "source /path/to/shell_env.sh &&"
        . "/bin/sh /path/to/script.sh";

答案 2 :(得分:0)

你无法在Perl 5中获取shell文件.Sourcing实际上是在目标shell的shell文件中运行命令;但是,打开并阅读文件是微不足道的:

#!/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";

答案 3 :(得分:0)

嗯..是下面的作弊?

#!/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

问题是,获取sh文件可能会做任何事情,而不只是将值X赋给变量Y ...

答案 4 :(得分:0)

我不知道这会有所帮助,但我觉得有必要想出一种在Perl中写这个的方法。我的目的是让Perl运行一个shell脚本,并将它设置的任何shell变量分配给Perl脚本中的命名变量。

其他的都是正确的,因为你“源”的任何shell脚本都将在子shell中。我想我可以使用“sh -x cmd”来至少让shell显示变量,因为它们已被设置。

这是我写的:

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);

你肯定可以做更多的错误检查,但如果您想要捕获的只是shell变量,这对我来说就是诀窍。

答案 5 :(得分:0)

是的,您现在可以使用Env::Modify module

执行此操作
$result = file_get_contents($url);

答案 6 :(得分:0)

我在一个项目的OP中满足了一个紧迫的需求,在该项目中,我需要通过采购定义环境的shell脚本来配置Perl脚本(就此而言,可以是任何一种语言)。

除了配置和环境设置外,我个人很少将采购用于其他任何事情(我知道采购的唯一另一个好理由是在shell脚本中导入函数,但我可能缺少一些创造性的用法)。

我的解决方案是从启动器脚本(在外壳中)中获取配置脚本,然后在同一启动器脚本中 exec Perl脚本(用Perl脚本有效替换启动器脚本,因此避免创建子流程。

# configuration_script.sh
export MY_ENV_VAR1=value1
export MY_ENV_VAR2=value2

# launcher_script.sh
. configuration_script.sh # source the configuration
exec /path/to/main_script.pl "$@" # could be any other language here (Python, Tcl, Ruby, C, Java...)

“ $ @”允许将命令行参数从启动器脚本传递到主脚本。

然后由主要脚本作者来检索环境(例如,在Perl中使用$ ENV {MY_ENV_VAR1})。