Come posso espandere una stringa come & # 8220; 1..15,16 & # 8221; in un elenco di numeri?
Domanda
Ho un'applicazione Perl che accetta dalla riga di comando un input come:
application --fields 1-6,8
Sono richiesto di visualizzare i campi come richiesto dall'utente sulla riga di comando.
Ho pensato di sostituire '-' con '..' in modo da poterli archiviare in array, ad esempio
$str = "1..15,16" ;
@arr2 = ( $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
Il problema qui è che @arr funziona bene (come dovrebbe) ma in @ arr2 l'intera stringa non viene espansa come elementi dell'array.
Ho provato a usare sequenze di escape ma senza fortuna.
Può essere fatto in questo modo?
Soluzione
Se si tratta di input dell'utente, non utilizzare la stringa eval su di esso se si hanno problemi di sicurezza.
Prova a utilizzare Number :: Range invece:
use Number::Range;
$str = "1..15,16" ;
@arr2 = Number::Range->new( $str )->range;
print for @arr2;
Per evitare di morire su un intervallo non valido, fare:
eval { @arr2 = Number::Range->new( $str )->range; 1 } or your_error_handling
C'è anche Set :: IntSpan , che utilizza - anziché ..:
use Set::IntSpan;
$str = "1-15,16";
@arr2 = Set::IntSpan->new( $str )->elements;
ma richiede che gli intervalli siano in ordine e non sovrapposti (è stato scritto per l'uso sui file .newsrc, se qualcuno ricorda quali sono). Consente inoltre intervalli infiniti (dove inizia la stringa - numero o termina numero -), su cui il metodo degli elementi graccherà.
Altri suggerimenti
Stai pensando a @ arr2 = eval ($ str);
Dal momento che stai prendendo input e valutandolo, devi stare attento.
Probabilmente dovresti @ arr2 = eval ($ str) if ($ str = ~ m / ^ [0-9.,] + $ /)
P.S. Non sapevo del pacchetto Number :: Range, ma è fantastico . Numero :: Range ftw.
Ho avuto lo stesso problema nel gestire l'output di Bit :: Vector :: to_Enum. L'ho risolto facendo:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
quindi anche nel mio file:
sub expand_range
{
return join(",",( Ho avuto lo stesso problema nel gestire l'output di Bit :: Vector :: to_Enum. L'ho risolto facendo:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
quindi anche nel mio file:
<*>
Quindi "1,3,5-7,9,12-15" si trasforma in "1,3,5,6,7,9,12,13,14,15".
Ho provato davvero a mettere quell'espansione nella seconda parte della s ///, quindi non avrei bisogno di quella funzione extra, ma non riuscivo a farlo funzionare. Mi piace questo perché mentre Number :: Range funzionerebbe, in questo modo non devo inserire un altro modulo per qualcosa che dovrebbe essere banale.
[0] .. Ho avuto lo stesso problema nel gestire l'output di Bit :: Vector :: to_Enum. L'ho risolto facendo:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
quindi anche nel mio file:
<*>
Quindi "1,3,5-7,9,12-15" si trasforma in "1,3,5,6,7,9,12,13,14,15".
Ho provato davvero a mettere quell'espansione nella seconda parte della s ///, quindi non avrei bisogno di quella funzione extra, ma non riuscivo a farlo funzionare. Mi piace questo perché mentre Number :: Range funzionerebbe, in questo modo non devo inserire un altro modulo per qualcosa che dovrebbe essere banale.
[1]));
}
Quindi "1,3,5-7,9,12-15" si trasforma in "1,3,5,6,7,9,12,13,14,15".
Ho provato davvero a mettere quell'espansione nella seconda parte della s ///, quindi non avrei bisogno di quella funzione extra, ma non riuscivo a farlo funzionare. Mi piace questo perché mentre Number :: Range funzionerebbe, in questo modo non devo inserire un altro modulo per qualcosa che dovrebbe essere banale.
@arr2 = ( eval $str ) ;
Funziona, anche se ovviamente devi stare molto attento con eval ().
Puoi usare eval:
$str = "1..15,16" ;
@arr2 = ( eval $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
Anche se questo è l'input dell'utente, probabilmente vorrai fare prima una convalida sulla stringa di input, per assicurarti che non abbiano inserito nulla di pericoloso.
Usa divisione:
@parts = split(/\,/, $fields);
print $parts[0];
1-6
print $parts[1];
8
Non puoi semplicemente mettere una stringa contenente ',' in un array e aspettarti che si trasformi in elementi (tranne se usi un po 'di magia nera Perl, ma non entreremo in quello qui)
Ma Regex e split sono i tuoi amici.