Resetting utils subtree.

This commit is contained in:
2024-11-12 11:09:35 +05:30
parent 5ddc9fa14d
commit ccd4693805
90 changed files with 11 additions and 15125 deletions
-288
View File
@@ -1,288 +0,0 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Sunday, 28th Apr., 2024
OBJECTIVE:
To provide a convenient way to perform RegEx operations like finding patterns and substituting them.
REFERENCES:
1) https://www.w3schools.com/python/python_regex.asp
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")
# To work with RegEx:
import re
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# Common RegEx patterns:
REGEX_EMAIL_ID = r"[\d\w_.+]*@[\d\w_]*.[\d\w]{2,}"
REGEX_PASSWORD = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[\d])(?=.*[!@#$%^&*()_+{}\[\]:;<>,.?~\\\/-]).{8,}$"
REGEX_NAME = r"^[\d\w .\-]{1,30}$"
REGEX_USERNAME = r"^[\d\w_]{8,25}$"
REGEX_CONTACT_NUMBER = r"\+?\d{0,3}\s*\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}"
REGEX_DATE = r"\b(?:\d{4}-\d{2}-\d{2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{1,2},?\s+\d{4}|\d{1,2}\/\d{1,2}\/\d{4}|\d{1,2}-\d{1,2}-\d{2}|\d{1,2}(?:st|nd|rd|th)\s+(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?),?\s+\d{4})\b"
REGEX_GSTIN = r"[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}"
REGEX_PAN = r"[A-Z]{5}[0-9]{4}[A-Z]{1}"
REGEX_IPV4 = (r"[0-9]{1,3}\." * 3) + r"[0-9]{1,3}"
REGEX_IPV6 = (r"[0-9a-fA-F]{1,4}:" * 7) + r"[0-9a-fA-F]{1,4}"
REGEX_IFSC = r"[A-Z]{4}0[A-Z0-9]{6}"
REGEX_UPI = r"[a-zA-Z0-9\.\-]{2,256}@[a-zA-Z][a-zA-Z]{2,64}"
REGEX_MAC_ADDRESS = r"([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\\.[0-9a-fA-F]{4}\\.[0-9a-fA-F]{4})"
REGEX_METRIC_WEIGHT = r"[\d\.]+[ ]?[k]?g"
# RegEx chars (append them to the patterns if needed):
REGEX_START = "^"
REGEX_END = "$"
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
def find(text, pattern, case_sensitive = True, dot_all = False):
"""
Returns a list of substrings that match the given RegEx pattern in the input text.
:param text: The text in which the pattern needs to be found.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: An array (list) of substring that match the pattern. Can be an empty list as well.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and clean the results:
matches = [match if type(match) is str else match[1] for match in re.findall(pattern, text, flags = flags)]
matches = [match for match in matches if len(match) > 0]
# Return the results:
return matches
# ---------------------------------------------------------------------------------------------------------------------
def find_first(text, pattern, case_sensitive = True, dot_all = False):
"""
Returns the first substring that matches the given RegEx pattern in the input text.
:param text: The text in which the pattern needs to be found.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: The first match as a string, or None if no match was found..
"""
matches = find(
text = text,
pattern = pattern,
case_sensitive = case_sensitive,
dot_all = dot_all
)
if not matches: return None
else: return matches[0]
# ---------------------------------------------------------------------------------------------------------------------
def replace(text, pattern, substitute_text, case_sensitive = True, dot_all = False):
"""
Replaces any substring in the text that matches the RegEx pattern.
:param text: The text in which the substitutions need to be made.
:param pattern: The RegEx pattern that needs to be substituted.
:param substitute_text: The text that will replace the matches that were found.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: The text with the substitutions. If no matches are found, the original string is returned.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and return the results:
return re.sub(pattern, substitute_text, text, flags = flags)
# ---------------------------------------------------------------------------------------------------------------------
def search(text, pattern, case_sensitive = True, dot_all = False):
"""
Checks if the given RegEx pattern occurs ANYWHERE in the text that was provided.
:param text: The text that needs to be matched against the pattern.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: True if the pattern matches, else False.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and return the results:
if re.search(pattern, text, flags = flags): return True
else: return False
# ---------------------------------------------------------------------------------------------------------------------
def match(text, pattern, case_sensitive = True, dot_all = False):
"""
Checks if the given text matches the RegEx pattern that was provided. The check is made only at the start of the
input string.
:param text: The text that needs to be matched against the pattern.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: True if the pattern matches, else False.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and return the results:
if re.match(pattern, text, flags = flags): return True
else: return False
# ---------------------------------------------------------------------------------------------------------------------
def split(text, pattern, case_sensitive = True, dot_all = False):
"""
Splits an input string based on the pattern that is being matched.
:param text: The text that needs to be matched against the pattern.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: True if the pattern matches, else False.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and return the results:
substrings = re.split(pattern, text, flags = flags)
if len(substrings) > 0 and substrings[0] == "": substrings.pop(0)
return substrings
# ---------------------------------------------------------------------------------------------------------------------
def to_json(text, pattern, case_sensitive = True, dot_all = False):
"""
Gives out a dict from the extracted features in a string. It is based on the concept of Named Groups.
Consider the following example (assuming the search is case-insensitive):
TEXT: "UPI/309258561479/14:17:35/UPI/omsainurses@okhdfc"
PATTERN: "upi/.*/(?P<time>.*)/.*/(?P<ref>.*)"
RESULT: {'time': '14:17:35', 'ref': 'omsainurses@okhdfc'}
:param text: The text that needs to be matched against the pattern.
:param pattern: The RegEx pattern to look for.
:param case_sensitive: Whether, or not, you want the operation to be case-sensitive.
:param dot_all: Allow all characters to be matched in ".".
:return: A dict with all the extracted features.
"""
# Prepare the flags:
flags = 0
if not case_sensitive: flags |= re.IGNORECASE
if dot_all: flags |= re.DOTALL
# Perform the RegEx operation, and return the results:
matches = re.search(pattern, text, flags = flags)
regex_json = matches.groupdict() if matches else {}
return regex_json
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
import json_utils
for narr in [
# r"UPI/309258561479/14:17:35/UPI/omsainurses@okhdf cb",
# r"UPI/309258561479/14:17:35/omsainurses@okhdf cb",
# r"NEFT-N095232403538009-RELIGARE BROKING LIMITED MAI",
r"Product listing - My product - 75g - Super combo pack",
r"Product listing - My product - 750 g",
r"0.5 kgs mini pack"
]:
result = to_json(
narr,
r"upi/.*/(?P<time>.*)/.*/(?P<ref>.*)",
case_sensitive = False
)
print(result)