2010-05-09 8 views
6

Sto cercando di ottenere un blocco di codice su una riga. Ho bisogno di un modo per ottenere il numero di elementi in una lista. Il mio codice attualmente appare così:Perl - Come ottenere il numero di elementi in un array anonimo, per tagliare concisamente i nomi di percorso

# Include the lib directory several levels up from this directory 
my @ary = split('/', $Bin); 
my @ary = @ary[0 .. $#ary-4]; 
my $res = join '/',@ary; 
lib->import($res.'/lib'); 

che è grande, ma mi piacerebbe fare che una linea, qualcosa di simile:

lib->import(join('/', ((split('/', $Bin)) [0 .. $#ary-4])) ); 

Ma naturalmente la sintassi $#ary è privo di significato nella riga sopra .

Esiste un modo equivalente per ottenere il numero di elementi in un elenco anonimo?

Grazie!

PS: La ragione per consolidare questo è che sarà nell'intestazione di un mucchio di script perl ausiliarie al l'applicazione principale, e voglio che questo piccolo incantesimo per essere più tagliare & pasta di prova.

Grazie a tutti

Non sembra essere una scorciatoia per il numero di elementi in un anonimo lista. Sembra una svista. Tuttavia le alternative suggerite erano tutte buone.

che sto andando con:

lib->import(join('/', splice(@{[split('/', $Bin)]}, 0, -4)).'/lib'); 

Ma Ether suggerito il seguente, che è molto più corretto e portatile:

my $lib = File::Spec->catfile(
       realpath(File::Spec->catfile($FindBin::Bin, ('..') x 4)), 
       'lib'); 
lib->import($lib); 
+2

Perché stai cercando di ottenere un blocco di codice fino a una riga? Se è solo per tagliare e incollare, allora questo è il tuo problema. Invece di fare una libreria per fare ciò che ti serve, non devi tagliare e incollare. Ecco perché esistono le subroutine. :) –

+0

Impossibile inserirlo in una lib, poiché questa è la riga di codice che imposta la directory di inclusione per le librerie personalizzate. Inoltre, non voglio :) Ma penso che sia comunque una domanda interessante. – NXT

risposta

3
lib->import(join('/', splice(@{[split('/', $bin)]}, 0, -4)).'/lib'); 
+0

Modifica, scusa per il mio stupido commento, ho letto il tuo codice sbagliato Questa è la risposta – NXT

+0

Questo dovrebbe funzionare così com'è, la giunzione con tre argomenti è splice (array, offset, length) - lo 0 specifica l'inizio, il -4 significa (lunghezza dell'array -4) Qualcun altro ha detto che 0 .. -4 è legale. considerare cosa significhi perl: 'contare da 0 a -4 '(non molto significativo). – pdehaan

2

Controllare la funzione splice.

+0

Grazie ma non funziona. 'splice (split ('/', $ Bin), -4)' dà un errore: il tipo di arg 1 da splice deve essere array (non split). Splice sembra voler un array ACTUAL. – NXT

+0

Un trucco: puoi usare @ {[split ...]}. Effettivamente, creerà un array, prenderà il suo riferimento e quindi lo deniverà. Inoltre, nota: hai bisogno di offset e lunghezza in splice: 0, -4. –

+0

@IK: Sì, anche l'offset e la lunghezza erano il mio ultimo problema. – NXT

1

È possibile manipolare un array (come la rimozione degli ultimi n elementi) con la funzione splice, ma è anche possibile generare una porzione di un array utilizzando un indice negativo (dove -1 indica l'ultimo elemento, -2 indica il penultimo, ecc.): es @list = @arr[0 .. -4] è legale.

Tuttavia,, sembra che si stia verificando un sacco di backflip che manipolano questi elenchi quando ciò che sembra essere desiderabile è il percorso di una directory lib. Non sarebbe più semplice fornire un argomento -I all'eseguibile perl oppure utilizzare $FindBin::Bin e File::Spec->catfile per individuare una directory relativa alla posizione dello script?

use strict; 
use warnings; 

use Cwd 'realpath'; 
use File::Spec; 
use FindBin; 

# get current bin 
# go 4 dirs up, 
# canonicalize it, 
# add /lib to the end 
# and then "use" it 

my $lib = File::Spec->catfile(
       realpath(File::Spec->catfile($FindBin::Bin, ('..') x 4)), 
       'lib'); 
lib->import($lib); 
+0

Grazie. Vedi altre risposte sul perché la giuntura non funziona. Ho provato gli indici negativi sulla fetta come si mostrano ma non ottengono alcun risultato. Sto già usando FindBin :: Bin per ottenere la directory di script, e File :: Spec non sembra fare nulla di utile per me (sarebbe bello se updir() prendesse un argomento in modo da poter andare su più di una directory – NXT

+0

@NXT: il "solito" modo di risalire le directory nel filesystem è usando 'realpath' di Cwd per canonizzare un percorso usando' ..'. – Ether

+0

grazie, ho capito ora. Non lo sapevo. In questo caso prenderò la concisione sulla correttezza, ma ne sto prendendo nota per il futuro – NXT

Problemi correlati