# 2012/06/25 v3.x import glob import os import re import sys def get_gredregex(ins): spr = r"(?P[\w])?\/(?P.*)(?!\\)\/(?P.*)(?!\\)\/(?P[\w])?" mpr = r"(?P[\w])?\/(?P.*)(?!\\)\/(?P\a)?(?P[\w])?" m = re.match(spr, ins) if re.match(spr, ins) else re.match(mpr, ins) if m: return (m.group('prefix'), m.group('regex'), m.group('substr'), m.group('suffix')) else: raise ValueError("Invalid re: invalid regex pattern: " + ins) def make_gredex(matup, opi): ''' a factory function of process_line function. process_line is the main regex algorithm how gred processes each text line. matup is a tuple, (prefix, match regex, replacement string, suffix). don't worry, you don't have to make it by yourself, this tuple is returned by "get_gredregex" function above. prefix and suffix are not used at this moment. opi is an option if regex is case-sensitive or not (if true, it's NOT case-sensitive). ''' prefix = matup[0] restr = matup[1] substr = matup[2] suffix = matup[3] rexes = None process_line = None mapat = None if opi: mapat = re.compile(restr, re.I) else: mapat = re.compile(restr) if prefix == "s" and substr != None: def process_line(each_line): return ( mapat.sub(substr, each_line), True ) else: def process_line(each_line): if mapat.search(each_line): return (each_line, True) else: return (each_line, False) return process_line def do_gred(args): ''' main function processes args, then scan line stream. ''' options = None repattern = None # get options, regex pattern and file list if re.search(r"^[-cinvH]+$", args[1]): options = args[1] repattern = args[2] fpaths = args[3:] else: repattern = args[1] fpaths = args[2:] # get options if options var defined. opc = True if options and "c" in options else False opi = True if options and "i" in options else False opn = True if options and "n" in options else False opv = True if options and "v" in options else False opH = True if options and "H" in options else False # get a tuple of regex patterns matup = get_gredregex(repattern) # options check: c and v only with //, c and n are exclusive. if opc and opn: raise ValueError('Invalid options: "c" and "n" are exclusive.') elif (opc or opv) and (matup[0] == "s" and matup[2]): raise ValueError('Invalid options: "c" or "v" allowed only with //.') # get process_line function that do gred process to each line based on regex pattern that user provided. process_line = make_gredex(matup, opi) # read all files in argv, and print the result according to the options. for each_fpath in fpaths: if ":" in each_fpath: each_fpath, enc = each_fpath.split(":") else: enc = sys.stdout.encoding file_entries = glob.glob(each_fpath) for filepath in file_entries: # target_file = open(filepath, mode="r", encoding=enc) target_file = open(filepath, mode="r", encoding=enc, errors='ignore') ln = 1 ct = 0 pct = 0 # in H option, if it's 0 line, 0 else 1. for each_line in target_file: resl = process_line(each_line) # if opc: just count matched lines. # (1) opc or not, if opc: if not opv and resl[1] == True: ct += 1 elif opv and resl[1] == False: ct += 1 else: # opv or not, if not opv and resl[1] == True: # if the line is 0 (pct == 0) and opH, if pct == 0 and opH: print("[%s]" % filepath, end=os.linesep) # if opn, print line number. if opn: print(ln, end="") print(resl[0], end="") #print(resl) if pct == 0: pct = 1 elif opv and resl[1] == False: if pct == 0 and opH: print("[%s]" % filepath, end=os.linesep) if opn: print(ln, end="") print(resl[0], end="") if pct == 0: pct = 1 ln += 1 if opc: if opH: print("[%s] " % filepath, end="") print(ct, end="") if pct == 0: pct = 1 target_file.close() if pct != 0: print(end=os.linesep) def show_help(): print("""gred.py [ivH[n][c]] /MATCH REGEX/ file... gred.py [inH] s/MATCH REGEX/SUBS REGEX/ file...\n""", end=os.linesep) try: do_gred(sys.argv) except UnicodeDecodeError: print("The targeted file may include unkown codec characters.", end=os.linesep) raise except: show_help() raise