2009-02-20 9 views
13

Come è possibile utilizzare la sintassi bash nel comando system() di Perl?Come posso usare la sintassi di bash nel sistema di Perl()?

Ho un comando che è bash-specifico, ad es. il seguente, che utilizza processo di sostituzione di bash:

diff <(ls -l) <(ls -al) 

vorrei chiamare da Perl, utilizzando

system("diff <(ls -l) <(ls -al)") 

ma mi dà un errore perché sta usando sh invece di bash per eseguire il comando :

sh: -c: line 0: syntax error near unexpected token `(' 
sh: -c: line 0: `sort <(ls)' 

risposta

45

Dire a Perl di invocare direttamente bash. Utilizzare il list variante di system() per ridurre la complessità del vostro citando:

my @args = ("bash", "-c", "diff <(ls -l) <(ls -al)"); 
system(@args); 

Si può anche definire una subroutine, se si ha intenzione di fare questo abbastanza spesso:

sub system_bash { 
    my @args = ("bash", "-c", shift); 
    system(@args); 
} 

system_bash('echo $SHELL'); 
system_bash('diff <(ls -l) <(ls -al)'); 
+1

+1 per utilizzare la variante di lista –

+3

Ciò impedisce anche di invocare/bin/sh solo per eseguire bash – cjm

+0

Accetto, la variante di lista è buona. – Frank

5
system("bash -c 'diff <(ls -l) <(ls -al)'") 

dovrebbe farlo, in teoria. L'opzione di Bash -c consente di passare un comando shell da eseguire, in base alla pagina man.

4

Il problema con le risposte di vladr è che il sistema non catturerà l'output in STDOUT dal comando (che di solito si vorrebbe), e inoltre non consente di eseguire più di un comando (dato l'uso di shift invece di accedere ai contenuti completi di @_).

simile al seguente potrebbe essere più adatto al problema:

my @cmd = ('diff <(ls -l) <(ls -al)', 'grep fu'); 
my @stdout = exec_cmd(@cmd); 
print join("\n", @stdout); 

sub exec_cmd 
{ 
    my $cmd_str = join(' | ', @_); 
    my @result = qx(bash -c '$cmd_str'); 
    die "Failed to exec $cmd_str: $!" unless($? == 0 && @result); 
    return @result; 
} 

Purtroppo questo non sarà impedire di invocare/bin/sh solo correre bash, ma non vedo una soluzione per questa edizione.

+0

Perché questa risposta non ha più +1? – Mir

0

Preferisco eseguire comandi bash in perl con i backtick "` ". In questo modo ottengo un valore di ritorno, ad es .:

my $value = \`ls`; 

Inoltre, non c'è bisogno di usare "bash -c" solo per eseguire un commmand. Per me va bene.

0

Ispirato alla risposta da @ errant.info, ho creato qualcosa di più semplice e ha lavorato per me:

my $line="blastn -subject <(echo -e \"$seq1\") -query <(echo -e \"$seq2\") -outfmt 6"; 
my $result=qx(bash -c '$line'); 
print "$result\n"; 

La variabile $ line introdotta permette di modificare gli ingressi ($ seq1 e $ seq2) ogni volta. Spero che aiuti!