2010-09-09 121 views
2

我們可以在perl腳本中輸入shell腳本嗎?我們可以在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的殼來獲得日期打印時我執行test3.pl

感謝 raghu

+0

爲什麼你不想爲此使用Perl的日期時間模塊? – ghostdog74 2010-09-09 10:43:10

+1

@ ghostdog74你甚至不需要一個模塊。標量上下文中的'localtime'函數產生一個幾乎相同的字符串:'perl -le'print scalar localtime'',你只需要得到時區並且它們是相同的。 – 2010-09-09 10:54:26

+0

嘿日期只是一個例子...它可以是任何東西在日期的地方(ls,chown,echo .....)在第一個文件中,我需要向perl發送什麼命令; – raghu 2010-09-16 11:43:16

回答

3

你不能做一個

system("source src.sh"); 

system()啓動一個新的子shell,你的環境變量沒有得到傳遞到外殼的Perl腳本在運行。即使你的shell腳本導出變量,它會將它們導出到子shell,而不是你的實際shell。

一個解決辦法是寫一個包裹腳本,

  1. 第一源的shell腳本,然後
  2. 運行Perl腳本
+1

這就是我通常所做的事情,但如果你想根據你所做的來源來獲取不同的文件,那麼這是行不通的。例如,假設你有三個數據庫,需要不同的環境來訪問它們。您事先不知道需要連接到哪個數據庫。在這種情況下,包裝方法下降。 – 2010-09-09 10:51:13

+1

@Chas。歐文斯:你說得對。 – codaddict 2010-09-09 11:19:57

0

你可以在Perl 5沒有源文件外殼。採購是從字面上在目標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"; 
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 ...

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變量。

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"; 
0

是的,你現在可以用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`;