2013-06-09 24 views
13

muszę wykonać następujący kod na powłoce bash:Jak prawidłowo używać nazwy zmiennej perl w ciągu odsunięć?

mogrify -resize 800x600 *JPG 

Ponieważ szerokość i wysokość są zmienne, to próbowałem:

`mogrify -resize $widx$hit *JPG` 

Jednak w zestawieniu, pojawia się błąd, że Global symbol "$widx" requires explicit package name at getattach.pl line 131. , ponieważ zamiast $ wid i x osobno, kompilator widzi $ widx jako nową niezadeklarowaną zmienną.

Próbowałem wstawiania podwójnych cudzysłowów w backticks, ale wykonanie kodu zatrzymany bez żadnych wiadomości.

Jaki jest właściwy sposób wstawiania nazw zmiennych w odsunięciach w celu wykonania powłoki? Czy można je połączyć?

+0

I nie wyrażenie w interpolacji bez Hack: http://stackoverflow.com/questions/3939919/can-perl-string-interpolation-perform-any-expression-evaluation tylko zmienne. –

Odpowiedz

20

Aby wstawić zmienną do dowolnego ciągu interpolację (czy to qq// lub qx lub qr//), po prostu robi "this is $foo!" jest wystarczająca: nazwę zmiennej (tu: $foo) jest ograniczona przez ! które nie mogą być częścią normalnej nazwy zmiennej .

Nie jest to takie łatwe, gdy części łańcucha mogą być częścią nazwy według zasad nazewnictwa Perla. Przykład:

my $genes = "ACTG$insert_genes_hereACTG"; 

Perl uważa nazwa zmiennej być . Problem ten można rozwiązać przez

  1. Używanie nawiasów klamrowych do oddzielania nazwę:

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

    to zawsze działa i jest elastycznym rozwiązaniem

  2. Połączenie łańcucha:

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

    Jest to nieco trudne dla non-qq -quot. Rozwiązaniem jest utworzenie tymczasowego zmienną, która posiada cały ciąg, a następnie interpoluje go do specjalnych cytatów:

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

    Wariant ten jest użycie sprintf interpolacji:

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

Jak na marginesie, wiele problemów interpolacji powłoki może być ominiętych przez , a nie za pomocą odsunięć, i zamiast tego należy użyć open lub system (w zależności od tego, czy potrzebujesz wyjścia).

z open:

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

while (<$command>) { do something } 

to całkowicie omija powłoki (i raczej bezpośrednio exec s), tak, masek musi być wykonywane ręcznie. To samo dotyczy system z więcej niż jednym argumentem.

+0

Doskonała odpowiedź. Dziękuję Ci. – Droidzone

5

Ten problem nie dotyczy tylko kliknięć. Problem może się zdarzyć za każdym razem, gdy interpolujesz zmienne Perla w ciągu znaków.

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

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

Problem polega na tym, że kompilator Perl nie może wiedzieć, gdzie zmienna nazwa („wid”) kończy się i stała nieco napisu („x”) rozpoczyna. Zakłada się więc, że szuka zmiennej o nazwie $widx - która nie istnieje.

Rozwiązaniem jest umieszczenie nazwy zmiennej w { ... }.

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

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

Oprócz innych dobrych odpowiedzi, można również korzystać z funkcji readpipe, co odpowiada backticks i operatora qx. Ale jak zwykła funkcja, możesz sprawować większą kontrolę nad interpolacją argumentów.

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