2010-09-09 7 views
2

Peut-on trouver un script shell dans le script Perl ??pouvons-nous trouver un script shell dans le script Perl?

Exemple: Programme 1:

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

programme 2:

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

Programme 3:

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

Comment SoURce le shell en Perl pour obtenir la date imprimée lorsque J'exécute test3.pl

grâce Raghu

+0

quelle raison vous ne voulez pas utiliser les modules de date-heure de Perl pour cela? – ghostdog74

+1

@ ghostdog74 Vous n'avez même pas besoin d'un module. La fonction 'localtime' dans un contexte scalaire produit une chaîne presque identique:' perl -le 'print scalar localtime'', vous avez juste besoin d'obtenir le fuseau horaire et ils seront identiques. –

+0

Hey Date est juste un exemple ... il peut être n'importe quoi à la place de la date (ls, chown, echo .....) quelle que soit la commande peut être dans le premier fichier que je dois source à la perl ; – raghu

Répondre

3

Vous ne pouvez pas faire un

system("source src.sh"); 

system() commence une nouvelle sous-shell, vos variables d'environnement ne sont pas transmis au shell script Perl est en cours d'exécution. Même si votre script shell exporte les variables, il les exportera vers la sous-shell, pas vers votre shell actuel.

Une solution serait d'écrire un script d'emballage qui

  1. sources d'abord le script shell et puis
  2. exécute le script Perl
+1

C'est ce que je fais généralement, mais cela ne fonctionne pas si vous voulez obtenir des fichiers différents en fonction de ce que vous faites. Par exemple, disons que vous avez trois bases de données et que vous avez besoin d'environnements différents pour y accéder. Vous ne savez pas à l'avance quelle base de données vous devrez vous connecter. Dans de tels cas, la méthode d'emballage tombe. –

+1

@Chas. Owens: Vous avez raison. – codaddict

0

Vous ne pouvez pas les fichiers shell source en Perl 5 Le sourcing exécute littéralement les commandes du fichier shell dans le shell cible; Cependant, il est trivial d'ouvrir et de lire le fichier:

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

Uhm .. est la tricherie ci-dessous?

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

Le problème est que l'approvisionnement du fichier sh peut faire tout, et non seulement attribuer une valeur X à la variable Y ...

0

Je ne sais pas que cela va aider, mais je me suis senti obligé de trouver un moyen d'écrire cela en Perl. Mon intention était de faire en sorte que Perl exécute un script shell, et d'assigner toutes les variables de shell qu'il définit à des variables similaires dans le script Perl.

Les autres sont corrects dans le fait que tout script shell que vous "source" va être dans un sous-shell. J'ai pensé que je pourrais utiliser "sh -x cmd" pour au moins que le shell affiche les variables telles qu'elles sont définies.

Voici ce que je l'ai écrit:

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

Il vous est certainement plus de contrôle d'erreur pouvait faire, mais cela a fait l'affaire pour moi, si tout ce que vous voulez capturer est variables shell.

1

Vous pouvez faire quelque chose de simple, comme ceci:

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

NOTE que ceci est différent de ce qui suit qui n'est pas recommandé:

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

Oui, vous pouvez maintenant le faire avec le 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`;