繁体   English   中英

从cli获取多种模式。 argparse Python3

[英]Take multiple patterns from cli. argparse Python3

我有一个grep的python版本,我正在为一项任务而构建。 我希望我的python模块从命令行采用多种模式,就像grep一样。 但是,无论我做什么,我都会与“调试”参数发生冲突。

这是当前从命令行(带有-h)的样子:

pgreper.py [-h] [--debug] pattern

目前,我只能使用一种模式进行搜索:

cat input.txt | ./pgreper.py "were"

我希望能够使用多种模式来搜索input.txt文件:

cat input.txt | ./pgreper.py "were" "you"

但是,当我尝试执行此操作时,出现以下错误:

pgreper.py: error: unrecognized argument: you

我知道这与我生成一个通过读取sys.argv [1]进行搜索的模式有关。 我将如何编辑脚本,以使其能够从sys.argv中采用多种模式,而又不影响已实现的可选参数?

非常感谢 :)

ps,请忽略我的评论,谢谢。

#!/usr/bin/python3

import sys
import re
import time
import datetime
import inspect
import argparse

parser = argparse.ArgumentParser(description='Python Grep.')
parser.add_argument('--debug', default='debug', action='store_true', help='Print debug messages')
parser.add_argument('pattern', type=str, help='Pattern for pgrepping')
args = parser.parse_args()


class CodeTrace(object):
    def __init__(self, line, pattern):
        self.line = line
        self.pattern = pattern

    # @staticmethod
    def trace(self, line, pattern):
        # Creating Timestamp
        ts = time.time()
        # Formatting Timestamp
        ts = datetime.datetime.fromtimestamp(ts).strftime('[%Y-%m-%d %H:%M:%S:%f]')
        stack = inspect.stack()
        # Retrieve calling class information
        the_class = stack[1][0].f_locals["self"].__class__
        # Retrieve calling method information
        the_method = stack[1][0].f_code.co_name
        the_variables = stack[1][0].f_code.co_varnames
        # Formats the contents of the debug trace into a readable format,
        # Any parameters passed to the method and the return value, are included in    the debug trace
        debug_trace = ("{} {}.{}.{} {} {} ".format(ts, str(the_class), the_method, the_variables, pattern, line))
        # Send out the debug trace as a standard error output
        sys.stderr.write(debug_trace + "\n")


class Grepper(object):
    def __init__(self, pattern):
        self.pattern = pattern

    # @CodeTrace.trace()
    def matchline(self, pattern):
        regex = re.compile(self.pattern)
        for line in sys.stdin:
            if regex.search(line):
                sys.stdout.write(line)
                if args.debug != 'debug':
                    (CodeTrace(line, pattern).trace(line, pattern))


def main():
    pattern = str(sys.argv[1])
    print(sys.argv)
    Grepper(pattern).matchline(pattern)

if __name__ == "__main__":
    main()    

您可以使用nargs关键字参数告诉argparse期望1个或多个参数

parser.add_argument('patterns', type=str, nargs='+', help='Pattern(s) for pgrepping')

这里+表示1或更大 然后,您可以组合以下模式:

pattern = '|'.join(['(?:{})'.format(p) for p in args.patterns])

并将其传递给您的grepper。 模式与| 首先将其置于非捕获组( (?:...) )中以确保将每个模式都视为不同的。

我将所有参数解析都放在main()函数中:

def main():
    parser = argparse.ArgumentParser(description='Python Grep.')
    parser.add_argument('--debug', action='store_true', help='Print debug messages')
    parser.add_argument('pattern', type=str, nargs='+', help='Pattern(s) for pgrepping')
    args = parser.parse_args()

    pattern = '|'.join(['(?:{})'.format(p) for p in args.pattern])
    Grepper(pattern, args.debug).matchline()

我还删除了--debug选项的默认设置。 使用store_true意味着它将默认为False 然后,您可以简单地测试args.debug是否为true。

您不需要将pattern两次传递给Grepper() 你可以简单地使用self.patternmatchline的方法,贯穿始终。 相反,我也会将args.debug传递给Grepper() (无需使其成为全局Grepper() )。

参数解析外观的快速演示,包括帮助消息:

>>> import argparse
>>> parser = argparse.ArgumentParser(description='Python Grep.')
>>> parser.add_argument('--debug', action='store_true', help='Print debug messages')
_StoreTrueAction(option_strings=['--debug'], dest='debug', nargs=0, const=True, default=False, type=None, choices=None, help='Print debug messages', metavar=None)
>>> parser.add_argument('pattern', type=str, nargs='+', help='Pattern(s) for pgrepping')
_StoreAction(option_strings=[], dest='pattern', nargs='+', const=None, default=None, type=<type 'str'>, choices=None, help='Pattern(s) for pgrepping', metavar=None)
>>> parser.print_help()
usage: [-h] [--debug] pattern [pattern ...]

Python Grep.

positional arguments:
  pattern     Pattern(s) for pgrepping

optional arguments:
  -h, --help  show this help message and exit
  --debug     Print debug messages
>>> parser.parse_args(['where'])
Namespace(debug=False, pattern=['where'])
>>> parser.parse_args(['were'])
Namespace(debug=False, pattern=['were'])
>>> parser.parse_args(['were', 'you'])
Namespace(debug=False, pattern=['were', 'you'])
>>> parser.parse_args(['--debug', 'were', 'you'])
Namespace(debug=True, pattern=['were', 'you'])

模式如下所示:

>>> args = parser.parse_args(['were', 'you'])
>>> args.pattern
['were', 'you']
>>> pattern = '|'.join(['(?:{})'.format(p) for p in args.pattern])
>>> pattern
'(?:were)|(?:you)'

相反,如果您希望所有模式都匹配,则需要更改Grepper()以采用多种模式并测试所有这些模式。 使用all()函数来提高效率(仅测试所需数量的模式):

def main():
    parser = argparse.ArgumentParser(description='Python Grep.')
    parser.add_argument('--debug', action='store_true', help='Print debug messages')
    parser.add_argument('pattern', type=str, nargs='+', help='Pattern(s) for pgrepping')
    args = parser.parse_args()

    Grepper(args.pattern, args.debug).matchline()

Grepper类变为:

class Grepper(object):
    def __init__(self, patterns, debug=False):
        self.patterns = [re.compile(p) for p in patterns]
        self.debug = debug

    def matchline(self, debug):
        for line in sys.stdin:
            if all(p.search(line) for p in self.patterns):
                sys.stdout.write(line)
                if self.debug:
                    CodeTrace(line, self.patterns).trace(line)

CodeTrace类进行适当的调整。

您的argparse参数配置不正确。 现在,这实际上就是您配置参数的方式。 检查Python文档中的argparse,因为那里有一个很好的例子。

格式应始终为yourscript.py -aARGUMENTVAL -bARGUMENTVAL ...etc. -a和-b样式很重要。

您的代码经过编辑,可以更好地使用argparse模块。 看看这是否更好(没有用于调试的动作参数):

import sys
import re
import time
import datetime
import inspect
import argparse

parser = argparse.ArgumentParser(description='Python Grep.')
parser.add_argument('-p', '--pattern', type=str, help='Pattern for pgrepping')
parser.add_argument('-d','--debug', type=str, default="false", help='Print debug messages')
args = vars(parser.parse_args());


class CodeTrace(object):
    def __init__(self, line, pattern):
        self.line = line
        self.pattern = pattern

    # @staticmethod
    def trace(self, line, pattern):
        # Creating Timestamp
        ts = time.time()
        # Formatting Timestamp
        ts = datetime.datetime.fromtimestamp(ts).strftime('[%Y-%m-%d %H:%M:%S:%f]')
        stack = inspect.stack()
        # Retrieve calling class information
        the_class = stack[1][0].f_locals["self"].__class__
        # Retrieve calling method information
        the_method = stack[1][0].f_code.co_name
        the_variables = stack[1][0].f_code.co_varnames
        # Formats the contents of the debug trace into a readable format,
        # Any parameters passed to the method and the return value, are included in    the debug trace
        debug_trace = ("{} {}.{}.{} {} {} ".format(ts, str(the_class), the_method, the_variables, pattern, line))
        # Send out the debug trace as a standard error output
        sys.stderr.write(debug_trace + "\n")


class Grepper(object):
    def __init__(self, pattern):
        self.pattern = pattern

    # @CodeTrace.trace()
    def matchline(self, pattern):
        regex = re.compile(self.pattern)
        for line in sys.stdin:
            if regex.search(line):
                sys.stdout.write(line)
                if args.debug != 'debug':
                    (CodeTrace(line, pattern).trace(line, pattern))


def main():
    pattern = str(args['pattern'])
    print(sys.argv)
    Grepper(pattern).matchline(pattern)

if __name__ == "__main__":
    main()

您可以提供逗号分隔的字符串来分隔模式-`p。 为此使用python强大的字符串函数

pattern = ((args['pattern']).replace(" ", "")).split(",");

以上将为您提供要查找的模式列表?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM