在argparse中处理带分隔符的字符串

时间:2014-08-20 10:12:15

标签: python argparse

我需要将带分隔符的字符串作为参数传递给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

如何实现存储上述定义的值?

感谢。

1 个答案:

答案 0 :(得分:2)

使用您的参数和命令行,我得到了

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参数的自定义Action中,但我认为它在解析后也能正常工作。