2013-06-09 15 views
13

Ich brauche den folgenden Code auf einem Bash-Shell auszuführen:Wie benutze ich einen Perl Variablennamen in Backticks richtig?

mogrify -resize 800x600 *JPG 

Da die Breite und Höhe sind Variablen, ich dies versucht:

`mogrify -resize $widx$hit *JPG` 

jedoch in der Zusammenstellung, ich den Fehler, dass Global symbol "$widx" requires explicit package name at getattach.pl line 131. Dies liegt daran, dass der Compiler anstelle von $ wid und x separat $ widx als neue nicht deklarierte Variable sieht.

Ich habe versucht, doppelte Anführungszeichen in die Backticks einzufügen, aber die Ausführung des Codes wurde ohne irgendwelche Nachrichten gestoppt.

Wie können Variablennamen in Backticks zur Shell-Ausführung eingefügt werden? Können sie verkettet werden?

+0

Und nicht Ausdruck in Interpolation ohne Hack: http://stackoverflow.com/questions/3939919/can-perl-string-interpolation-perform-any-expression-evaluation, nur Variablen. –

Antwort

20

Um eine Variable in jedem Interpolations-String einfügen (sei es qq// oder qx oder qr//), nur "this is $foo!" tun genügt: Der Name der Variablen (hier: $foo) durch die ! begrenzt, die nicht Teil eines normalen Variablenname sein kann .

Es ist nicht so einfach, wenn Teile der Zeichenkette durch Perls Benennungsregeln Teil des Namens sein könnten. Beispiel:

my $genes = "ACTG$insert_genes_hereACTG"; 

Perl hält die Variablennamen zu sein. Dies kann durch

  1. Mit curlies gelöst werden, um den Namen zu begrenzen:

    my $genes = "ACTG${insert_genes_here}ACTG"; 
    

    Dies funktioniert immer und ist eine flexible Lösung

  2. verketten die Zeichenfolge:

    my $genes = "ACTG" . $insert_genes_here . "ACTG"; 
    

    Dies ist ein bisschen schwierig für nicht-qq -Quoten. Eine Lösung ist es, eine temporäre Variable zu erzeugen, die die gesamte Zeichenfolge hält, und interpoliert dann in spezielle Zitate:

    my $command = "mogrify -resize " . $wid . "x" . $hit. " *JPG"; 
    `$command`; 
    

    Eine Variante davon ist sprintf Interpolation zu verwenden:

    my $command = sprintf 'mogrify -resize %dx%d *JPG', $wid, $hit; 
    

Wie Nebenbei können viele Shell-Interpolationsprobleme durch nicht mit Backticks umgehen und stattdessen open oder system (je nachdem, ob Sie Ausgabe benötigen oder nicht) verwendet werden.

Mit open:

open my $command, "-|", "mogrify", "-resize", $wid . "x" . $hit, glob("*JPG") 
    or die ...; 

while (<$command>) { do something } 

Diese umgeht vollständig die Schale (und eher exec s direkt), so hat Globbing manuell durchgeführt werden. Gleiches gilt für system mit mehr als einem Argument.

+0

Ausgezeichnete Antwort. Vielen Dank. – Droidzone

5

Dieses Problem ist nicht spezifisch für Backticks. Das Problem kann immer dann auftreten, wenn Sie Perl-Variablen in einer Zeichenfolge interpolieren.

my $wid = 800; 
my $hit = 600; 

print "$widx$hit"; # this has the same problem 

Das Problem ist, dass der Perl-Compiler kann nicht wissen, wo der Variablenname („wid“) endet und das feste Bit der Zeichenfolge („x“) beginnt. Es nimmt also an, dass es nach einer Variablen namens $widx sucht - die nicht existiert.

Die Lösung ist, den Namen der Variablen in { ... } zu setzen.

my $wid = 800; 
my $hit = 600; 

print "${wid}x$hit"; # This works 
1

Zusätzlich zu den anderen guten Antworten, können Sie auch die readpipe Funktion verwenden, die auf Backticks entspricht und der qx Operator. Aber wie eine reguläre Funktion können Sie eine bessere Kontrolle darüber haben, wie die Argumente interpoliert werden.

$output = readpipe("mogrify -resize $wid" . "x$hit *.JPG"); 
$output = readpipe(sprintf "mogrify -resize %dx%d *.JPG", $wid, $hit); 
Verwandte Themen