Мне нужно передать строку с разделителем в качестве аргумента скрипту Python. Итак, я использовал

parser.add_argument('--filter', default=None, nargs='*', action="append")

Входными данными для сценария могут быть любые из следующих:

process.py --filter include:a.txt,b.txt exclude:c.txt, d.txt
process.py --filter a.txt   => This should be considered as include:a.txt
process.py --filter include:b.txt --filter exclude:d.txt
process.py --filter exclude:c.txt --filter b.txt

Файлы a.txt, b.txt, c.txt и d.txt содержат несколько строк с шаблонами регулярных выражений.

Мне нужно отфильтровать отчет по ключевым словам (включить / исключить). В первых двух случаях, описанных выше, после фильтрации необходимо создать только один отчет, тогда как в третьем и четвертом случаях необходимо создать два отчета. Итак, мне нужно сохранить данный ввод как

Case 1:
filter1 => include => a.txt, b.txt
           exclude => c.txt, d.txt

Case 2:
filter1 => include => a.txt

Case 3:
filter1 => include => b.txt
filter2 => exclude => d.txt

Case 4:
filter1 => exclude => c.txt
filter2 => include => b.txt

Как я могу добиться сохранения значений, как определено выше?

Спасибо.

0
Hema 20 Авг 2014 в 14:12
1
Вы уверены, что хотите, чтобы ваши фильтры были --filter1 --filter2 и т. д.? или было бы лучше список фильтров? В любом случае я предлагаю изучить: docs.python.org/dev/library/argparse .html # action внизу этого раздела приведен пример настраиваемого действия, он должен позволить вам делать то, что вы хотите.
 – 
user3012759
20 Авг 2014 в 15:14
Поэкспериментируйте, чтобы увидеть, что вы получите в sys.argv с различными входами. Вам может понадобиться больше цитат.
 – 
hpaulj
20 Авг 2014 в 15:19

1 ответ

Лучший ответ

С вашим аргументом и командной строкой я получаю

Namespace(filter=[['include:a.txt,b.txt', 'exclude:c.txt,', 'd.txt']])
Namespace(filter=[['a.txt']])
Namespace(filter=[['include:b.txt'], ['exclude:d.txt']])
Namespace(filter=[['exclude:c.txt'], ['b.txt']])

Эти значения точно отражают то, что синтаксический анализатор получил в sys.argv[1:].

Этот список filter должен быть легко обработан для генерации нужных вам значений. Вам больше не нужно ничего делать в argparse. Попытка сделать это в argparse не сэкономит ни усилий, ни логики.

Тем не менее, я могу придумать некоторые вещи, которые упростили бы логику.

Устраните пространство в exclude:c.txt, d.txt. или заключите эту подстроку в кавычки.

Отбросьте неявное требование include.

Вместо одной опции --filter определите две опции, --include и --exclude (и, возможно, позиционную для обработки неявного 'include'):

parser.add_argument('--include','-i', default=[], nargs='*', action="append")
parser.add_argument('--exclude','-e', default=[], nargs='*', action="append")
parser.add_argument('include', nargs='*', action="append")

Производство

'a.txt' => 
Namespace(exclude=[], include=[['a.txt']])

'--include a.txt b.txt --exclude c.txt d.txt' =>
Namespace(exclude=[['c.txt', 'd.txt']], include=[['a.txt', 'b.txt'], []])

Простая функция для анализа значений filter:

def decode(values):
    filters = []
    for f in values:
        filter = {}
        for text in f:
            words = text.split(':')
            if len(words)==1:
                words = ['include']+words
            files = words[1].split(',')
            if words[0] == 'include':
                filter['include'] = files
            elif words[0] == 'exclude':
                filter['exclude'] = files
            else:
                filter['unknown'] = files
        filters.append(filter)
    return filters

Что можно использовать как:

args = parser.parse_args()
filters = decode(args.filter)

Производство для ваших 4-х корпусов:

[{'exclude': ['c.txt', 'd.txt'], 'include': ['a.txt', 'b.txt']}]
[{'include': ['a.txt']}]
[{'include': ['b.txt']}, {'exclude': ['d.txt']}]
[{'exclude': ['c.txt']}, {'include': ['b.txt']}]

Я думаю, единственное, чего здесь не хватает, - это обработки пространства в exclude:c.txt, d.txt. Для этого он производит: [{'exclude': ['c.txt', ''], 'include': ['d.txt']}]. То есть он интерпретирует это как неявное include.

Теоретически его можно было бы включить в настраиваемое действие для аргумента --filter, но я думаю, что он работает так же хорошо после синтаксического анализа.

2
hpaulj 22 Авг 2014 в 05:53