Argparse: дифференцировать аргументы на основе регулярных выражений? - PullRequest
0 голосов
/ 27 декабря 2018

Можно ли провести различие между аргументами, основанными на регулярном выражении с argparse?

Я бы хотел, чтобы мой сценарий принимал либо IP-адрес, либо сетевой адрес, но должен иметь возможность различать два, потому чтовызов API-интерфейса требует, чтобы я указал, какой из них используется.Я бы предпочел не использовать явный флаг, чтобы указать, какой аргумент используется, вместо этого использовать регулярное выражение, но не уверен, что это возможно?

Пример использования:

ip-lookup.py 192.168.1.1

192.168.1.1 следуетбыть назначенным аргументу с именем 'ip'

ip-lookup.py 192.168.0.0/16
ip-lookup.py 192.168.0.0 255.255.0.0
ip-lookup.py 192.168.0.0/255.255.0.0

192.168.0.0 / 16 должен быть назначен аргументу с именем 'network'

код:

parser = argparse.ArgumentParser(description='Lookup an IP address or network in the backend IPAM system.')
parser.add_argument('ip', help='IP host address', type=str, required=False, **regex to match on IP address**)
parser.add_argument('network', help='IP network address', type=str, required=False, **regex to match on IP network**)

args = parser.parse_args()

args.ip         -> should only exist if the user entered an IP address as parameter
args.network    -> should only exist if the user entered an IP network as parameter

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Для всех, кто заинтересовался, я также рассмотрел некоторые альтернативы argparse, такие как Click, но, поскольку использование аргументов таким способом не соответствует юникс-способу использования позиционных аргументов, он, похоже, не является встроенным.

Мне удалось заставить его работать, непосредственно проанализировав sys.argv.Не очень элегантно, но работает как положено:

import sys
import ipaddress

USAGE = """
 Usage:
    \t ip-lookup.py 192.168.1.1
    \t ip-lookup.py 192.168.0.0/16
    \t ip-lookup.py 192.168.0.0 255.255.0.0
    \t ip-lookup.py 192.168.0.0/255.255.0.0    
    """

# Parse command-line arguments
if (len(sys.argv) < 2):
    print('\n ### Please specify an IP address or subnet as arguments. ###')
    print(USAGE)
elif (len(sys.argv) == 2 and '/' in sys.argv[1]): # x.x.x.x/xx
        try:
            prefix = ipaddress.IPv4Network(sys.argv[1])
            urlparams = 'network?network='
        except:
            print('### Error: not a valid network address ###')
elif (len(sys.argv) == 2 and '/' not in sys.argv[1]): # x.x.x.x
        try:
            ip = ipaddress.IPv4Address(sys.argv[1])
            urlparams = 'ipv4address?status=USED&ip_address='
        except:
            print('### Error: not a valid IP address ###')
elif (len(sys.argv) == 3): # x.x.x.x x.x.x.x
    if(sys.argv[2].startswith('255.')):
        try:
            prefix = ipaddress.IPv4Network(sys.argv[1] + '/' + sys.argv[2])
            urlparams = 'network?network='
        except:
            print('### Error: not a valid network address ###')        
else:
    print('\n ### Error: too many arguments given. ###')
    print(USAGE)
0 голосов
/ 27 декабря 2018

Я бы подошел к этому, определив непозиционные аргументы (-- перед ними при определении).Например,

import argparse
parser = argparse.ArgumentParser()

parser.add_argument('--ip', help='IP host address', type=str, required=False)
parser.add_argument('--network', help='IP network address', type=str, required=False)

args = parser.parse_args()

print(getattr(args, 'ip'))
print(getattr(args, 'network'))

Теперь вы можете вызвать это с помощью test.py --ip 192.168.1.1 или test.py --network 192.168.0.0/255.255.0.0.Это вернет соответственно:

192.168.1.1
None

или

None
192.168.1.1/255.255.0.0

Обратите внимание, что --network '192.168.1.1 255.255.0.0' потребуется, если строка содержит пробел.

...