2011-01-18 20 views
8

Escribo una aplicación de línea de comando y me gustaría que el usuario pueda ingresar números como números individuales o como un rango. Así, por ejemplo:Entrada de línea de comandos de análisis para los números

$ myapp -n 3,4,5,6 

o

$ myapp -n 3-6 

Me gustaría que mi aplicación para que los pongan en una lista de Python por ejemplo, [3, 4, 5, 6] estoy usando optparse, pero no estoy seguro de cómo crear la lista a partir de estos dos estilos de entradas. Algún código de ejemplo sería genial.

EDITAR

Me gustaría ser capaz de entrar en varios rangos demasiado:

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

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

Respuesta

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) 

produce

% 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

Gracias. Esto parece funcionar perfectamente para mis requerimientos. – normski

+0

Una cosa más me gustaría poder ingresar a múltiples rangos, por ejemplo, myapp 22-27, 51-64 – normski

+1

@normski: Correcto.El código anterior puede manejarlo, siempre y cuando no coloque un espacio entre '22-27,' y '51-64'. (De esta manera, toda la cadena se carga en 'opt.n'.) – unutbu

3

Si usted tiene la n-ARG en una cadena que puede hacer:

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

Algunos ejemplos:

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

Me gusta esta solución. Me gustaría ver alguna validación de entrada, eso es todo :) Sería bastante subóptimo si la lista de entrada es gigantesca, pero sospecho que no lo es. – Skurmedel

+2

Esto tampoco incluye el límite superior. –

1

Utilice Python's range function. Analice la entrada de su usuario, dividiéndola por el carácter '-' y luego pase esos parámetros al rango.

Su código podría ser algo como esto:

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

Si entran en números individuales, sólo puede analizar esto en una lista bastante facilidad.

+1

Esto no incluirá el límite superior, como se desee. –

+1

Luego solo agrega 1 al segundo parámetro ... –

1

Usted puede utilizar optparse biblioteca.

Ejemplo:

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

Puede definir su argumento y utilizar optparse callback para procesar su entrada antes de guardarla:

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 

haciendo ahora:

python2.7 test.py -r 1-5 

Salida:

[1, 2, 3, 4, 5] 
Cuestiones relacionadas