2011-01-18 11 views
8

Sto scrivendo un'applicazione a riga di comando e vorrei che l'utente fosse in grado di inserire numeri come numeri singoli o come intervallo. Così, per esempio:Parsing input da riga di comando per i numeri

$ myapp -n 3,4,5,6 

o

$ myapp -n 3-6 

Vorrei che la mia applicazione per mettere questi in una lista Python ad esempio, [3, 4, 5, 6] sto usando optparse, ma non sono sicuro di come creare la lista da questi due stili di input. Qualche esempio di codice sarebbe fantastico.

EDIT

Mi piacerebbe essere in grado di entrare più intervalli troppo:

$ myapp -n 22-27, 51-64 
+0

Correlato: http://stackoverflow.com/questions/4248399/page-range-for-printing-algorithm –

risposta

13
import argparse 

def parse_range(astr): 
    result = set() 
    for part in astr.split(','): 
     x = part.split('-') 
     result.update(range(int(x[0]), int(x[-1]) + 1)) 
    return sorted(result) 

parser = argparse.ArgumentParser() 
parser.add_argument('-n', type=parse_range) 
args = parser.parse_args() 
print(args.n) 

cede

% script.py -n 3-6 
[3, 4, 5, 6] 

% script.py -n 3,6 
[3, 6] 

% script.py -n 22-27,51-64 
[22, 23, 24, 25, 26, 27, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64] 
+1

Grazie. Questo sembra funzionare perfettamente per le mie esigenze. – normski

+0

Un'altra cosa che mi piacerebbe poter inserire più intervalli, ad es., Myapp 22-27, 51-64 – normski

+1

@normski: Right.Il codice sopra può gestirlo, purché non si metta uno spazio tra '22-27,' e '51-64'. (In questo modo l'intera stringa viene caricata in 'opt.n'.) – unutbu

3

Se avete la n-Arg in una stringa si può fare:

def f(s): 
    if '-' in s: 
     i = s.index('-') 
     return range(*map(int, s.split('-'))) 
    return map(int, s.split(',')) 

Alcuni esempi:

In [3]: s = '1, 2, 3, 4, 5, 6' 

In [4]: f(s) 
Out[4]: [1, 2, 3, 4, 5, 6] 

In [5]: f('3-6') 
Out[5]: [3, 4, 5] 

In [6]: f('3-16-3') 
Out[6]: [3, 6, 9, 12, 15] 
+0

Mi piace questa soluzione. Mi piacerebbe vedere alcune validazioni di input, questo è tutto davvero :) Sarebbe abbastanza sub-ottimale se la lista di input fosse gigantesca, ma sospetto che non lo sia. – Skurmedel

+2

Questo non include neanche il limite superiore. –

1

Utilizzare Python's range function. Analizza l'input dell'utente, dividendolo con il carattere '-', quindi passa quei parametri all'intervallo.

Il codice potrebbe essere simile a questo:

parameters = input.split('-') 
completeRange = range(int(parameters[0]), int(parameters[1])) 

Se entrano singoli numeri, si può solo analizzare che in un elenco abbastanza facilmente.

+1

Questo non includerà il limite superiore, come desiderato. –

+1

Quindi aggiungi 1 al secondo parametro ... –

1

È possibile utilizzare optparse biblioteca.

Esempio:

from optparse import OptionParser 

opt_parser = OptionParser(version="%prog 0.1") 
opt_parser.usage = '%prog [options]\n\nTCP protocol reengineering tool' 

# Options 
opt_parser.add_option('-n', default="1,2,3") 
(options, args) = opt_parser.parse_args() 

list = [] 
for s in options.n.split(","): 
    list.append(int(s)) 
2

È possibile definire il vostro argomento e utilizzare optparse callback per elaborare il vostro input prima di salvarlo:

from optparse import OptionParser 

parser = OptionParser() 

def create_range_callback(option, opt, value, parser): 
    i, j = map(int, value.split('-')) 
    setattr(parser.values, option.dest, range(i, j+1)) 

parser.add_option("-r", "--range", action="callback", 
        callback=create_range_callback, 
        type="string", dest='list') 

(options, args) = parser.parse_args() 

print options.list 

facendo ora:

python2.7 test.py -r 1-5 

uscita:

[1, 2, 3, 4, 5] 
Problemi correlati