2015-01-13 8 views
0

나는 grep의 파이썬 버전을 가지고 있는데, 나는 할당을 위해 만들고있다. 파이썬 모듈이 grep과 같이 명령 줄에서 여러 패턴을 가져 오도록하고 싶습니다. 그러나 내가하는 일과 상관없이 나는 '디버그'논쟁과 계속 충돌한다.cli에서 여러 패턴 가져 오기. argparse Python3

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

내가 싶습니다 : 순간

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

나는 단지 하나 개의 패턴으로 검색 할 수 있습니다 :

는 현재 명령 (-h와) 라인에서 모습입니다 input.txt 파일을 여러 가지 패턴으로 검색 할 수 있습니다.

cat input.txt | ./pgreper.py "were" "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()  
+0

'main()'함수가'args'에 저장된 구문 분석 된 인수를 무시하는 이유는 무엇입니까? –

+0

죄송합니다, 무슨 뜻인지 모르겠군요 : ( –

+0

'argparse'가'sys.argv'를 구문 분석 한 다음 그 결과를 무시하고 직접'sys.argv [1]'을 사용하십시오. –

답변

2

당신은 nargs keyword argument 사용하여 1 개 이상의 인수를 기대하는 argparse을 알 수 있습니다 : 여기 +

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

1 이상을 의미한다. 다음 패턴을 결합 할 수 있습니다.

그레이퍼로 전달하십시오. 패턴은 처음에는 비 포획 그룹 ((?:...))에 배치 된 후 |과 결합되어 각 패턴이 별개로 취급됩니다.

나는 모든 인수가 여기에 main() 기능에 구문 분석 배치 것

: 나는 또한 --debug 옵션의 기본을 제거

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() 

; store_true을 사용하면 기본값은 False입니다. args.debug이 true인지 아닌지 간단하게 테스트 할 수 있습니다.

Grepper()pattern 번을 두 번 전달할 필요가 없습니다. 전체적으로 matchline 메소드에서 self.pattern을 사용할 수 있습니다. 대신 args.debug에서 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()을 변경하여 여러 패턴을 가져 와서 모든 패턴을 테스트해야합니다.

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 클래스가된다 : 효율적인 (필요한만큼의 패턴을 테스트) 있는지 확인하기 위해 all() function를 사용

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 클래스에 대한 적절한 조정과 함께.

+0

J 궁금 해서요, 그게 어떻게 CLI에 구현 될까요? 예 : cat input.txt | .pgreper.py "늑대가있다" –

+0

@jeff_h :'./pgrepper.py was wolf'. 데모에 포함 된'--help' 결과물도 참고하십시오. –

+0

이것은 정말 좋습니다. 지금까지 모든 도움을 주셔서 감사합니다. :) 그러나 에테르 패턴이 들어있는 것은 두 패턴으로 인쇄하는 것보다 에테르 패턴이있는 것으로 인쇄됩니다. 내가 뭘 하려는지 미안, 분명히하지 않았다면 : ( –

0

argparse 인수 구성이 올바르지 않습니다. 이것은 실제로 여러분이 인수를 구성하는 방법입니다. argparse에 대한 Python 문서를 확인하십시오. 거기에 아주 좋은 예가 있습니다.

형식은 항상 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 재잘을 분리하는 쉼표로 구분 된 문자열을 제공 할 수 있습니다 "당신했다." 그에 대한 파이썬의 강력한 문자열 함수를 사용하십시오.

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

위의 패턴 목록을 찾으실 수 있습니까?

+0

개선되었으므로 다음과 같이 실행했습니다 : cat input.txt | ./pgreper.py --p "the"--p "vir" 그러나 스크립트는 이제 첫 번째 패턴을 무시하고 두 번째 패턴을 포함하는 행만 인쇄합니다. –

+0

쉼표로 구분 된 문자열을 제공 할 수없는 이유는 무엇입니까? – ha9u63ar