Come posso espandere una stringa come & # 8220; 1..15,16 & # 8221; in un elenco di numeri?

StackOverflow https://stackoverflow.com/questions/1016766

  •  06-07-2019
  •  | 
  •  

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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top