From 6f067fe938060291803084484388f062f032dbae Mon Sep 17 00:00:00 2001 From: Augusto Gunsch Date: Fri, 11 Nov 2022 18:52:44 +0100 Subject: [PATCH] Initial commit --- requirements.txt | 1 + sub.py | 116 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 requirements.txt create mode 100755 sub.py diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4ae7986 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +colorama==0.4.3 diff --git a/sub.py b/sub.py new file mode 100755 index 0000000..430a806 --- /dev/null +++ b/sub.py @@ -0,0 +1,116 @@ +#!/bin/python3.9 +import re +import hashlib +import os +from sys import argv, stderr +from os.path import basename +from colorama import init, Fore, Back, Style + +init(autoreset=True) + +if len(argv) <= 3: + print('usage: {0} [REGEX] [SUB] [FILES...]'.format(basename(__file__)), file=stderr) + exit(1) + +regex = argv[1] +sub = argv[2] +files = argv[3:] +replace_all = False +quit_loop = False +sub_count = 0 +match_count = 0 + +def prompt(matchobj, line, line_n, file): + global replace_all + global quit_loop + global sub_count + global match_count + + if quit_loop: + return matchobj.group(0) + + + replaced_match = re.sub(regex, sub, matchobj.group(0)) + + if replaced_match == matchobj.group(0): + return replaced_match + + match_count += 1 + + if replace_all: + sub_count += 1 + return replaced_match + + highlighted = line.replace(matchobj.group(0), + Back.RED + matchobj.group(0) + Back.RESET) + replaced = line.replace(matchobj.group(0), + Back.YELLOW + Fore.BLACK + replaced_match + Back.RESET + Fore.RESET) + + print(Fore.GREEN + Style.BRIGHT + file) + + print(Fore.YELLOW + Style.BRIGHT + str(line_n), end='') + print(':{0}'.format(highlighted)) + + print('Becomes the following:') + + print(Fore.YELLOW + Style.BRIGHT + str(line_n), end='') + print(':{0}'.format(replaced)) + + print() + + while True: + answer = input('Confirm the change? [Y/n/a/q] ').lower() + + if answer in ['y', 'yes', '']: + sub_count += 1 + print() + return replaced_match + elif answer in ['n', 'no']: + print() + return matchobj.group(0) + elif answer in ['a', 'all']: + sub_count += 1 + replace_all = True + return replaced_match + elif answer in ['q', 'quit']: + quit_loop = True + return matchobj.group(0) + + print('Invalid answer. Please type again.') + +def filter_file(fname): + with open(fname, 'r') as file: + contents = file.read() + + lines = contents.splitlines() + + lines = [ + re.sub(regex, + lambda matchobj: prompt(matchobj, line, line_n, fname), + line) + for (line_n, line) in enumerate(lines) + ] + + new_contents = '\n'.join(lines) + + hash_old = hashlib.md5(contents.encode()) + hash_new = hashlib.md5(new_contents.encode()) + + if hash_old.digest() != hash_new.digest(): + with open(fname, 'w') as file: + file.write(new_contents) + file.write('\n') + +for file in files: + if os.access(file, os.W_OK): + filter_file(file) + + if quit_loop: + break + +if match_count == 0: + print(Fore.RED + Style.BRIGHT + 'No matches found.') +else: + print(Fore.YELLOW + Style.BRIGHT + 'Made {0} of {1} substitutions.'. + format(Fore.WHITE + str(sub_count) + Fore.YELLOW, + Fore.WHITE + str(match_count) + Fore.YELLOW))