|
1
|
|
|
from itertools import pairwise |
|
2
|
|
|
from re import search, match |
|
3
|
|
|
from typing import Tuple |
|
4
|
|
|
|
|
5
|
|
|
|
|
6
|
|
|
def translate_brackets(pattern: str, pair: Tuple[int, int]) -> Tuple[int, str]: |
|
7
|
|
|
if pair[1] - pair[0] == 1: |
|
8
|
|
|
return pair[0], '' |
|
9
|
|
|
else: |
|
10
|
|
|
sub_pattern = pattern[pair[0]:pair[1] + 1] |
|
11
|
|
|
if sub_pattern.startswith('[!'): |
|
12
|
|
|
return pair[0], '[^' + pattern[pair[0] + 1:pair[1]].replace('.', r'\.').replace('*', r'\*').replace('?', |
|
13
|
|
|
r'\?') + ']' |
|
14
|
|
|
else: |
|
15
|
|
|
return pair[0], '[' + pattern[pair[0] + 1:pair[1]].replace('.', r'\.').replace('*', r'\*').replace('?', |
|
16
|
|
|
r'\?') + ']' |
|
17
|
|
|
|
|
18
|
|
|
|
|
19
|
|
|
def translate_non_pattern(pattern: str, pair: Tuple[int, int]) -> Tuple[int, str]: |
|
20
|
|
|
return pair[0], pattern[pair[0]:pair[1]].replace('.', '\.').replace('*', '.*').replace('?', '.').replace('[', '\[').replace(']', '\]') |
|
21
|
|
|
|
|
22
|
|
|
|
|
23
|
|
|
def find_matching_left_bracket(string: str, right_bracket_index: int, stop_index: int) -> (int, int): |
|
24
|
|
|
for i in range(right_bracket_index, stop_index - 1, -1): |
|
25
|
|
|
if string[i] == '[': |
|
26
|
|
|
return i, right_bracket_index |
|
27
|
|
|
|
|
28
|
|
|
|
|
29
|
|
|
def find_non_brackets(pattern: str, brackets: Tuple[Tuple[int, int]]) -> Tuple[Tuple[int, int]]: |
|
30
|
|
|
non_brackets = [(0, len(pattern))] * (len(brackets) + 1) |
|
31
|
|
|
if len(brackets) == 0: |
|
32
|
|
|
return non_brackets |
|
33
|
|
|
for i in range(len(non_brackets)): |
|
34
|
|
|
if i == 0: |
|
35
|
|
|
non_brackets[i] = (non_brackets[i][0], brackets[i][0]) |
|
36
|
|
|
elif i == len(non_brackets) - 1: |
|
37
|
|
|
non_brackets[i] = (brackets[i - 1][1]+1, non_brackets[i][1]) |
|
38
|
|
|
else: |
|
39
|
|
|
non_brackets[i] = (brackets[i - 1][1] + 1, brackets[i][0]) |
|
40
|
|
|
return tuple([i for i in non_brackets if i[0] < i[1]]) |
|
41
|
|
|
|
|
42
|
|
|
|
|
43
|
|
|
def find_brackets(pattern: str) -> Tuple[Tuple[int, int]]: |
|
44
|
|
|
right_brackets = [k for k, v in enumerate(pattern) if v == ']'] |
|
45
|
|
|
brackets_index_pairs = tuple(filter(lambda x: x, map(lambda x: find_matching_left_bracket(pattern, x[1], x[0]), |
|
46
|
|
|
pairwise([0] + right_brackets)))) |
|
47
|
|
|
print(right_brackets) |
|
48
|
|
|
print(brackets_index_pairs) |
|
49
|
|
|
return brackets_index_pairs |
|
50
|
|
|
|
|
51
|
|
|
|
|
52
|
|
|
def translate_pattern(pattern: str) -> str: |
|
53
|
|
|
brackets_index_pairs = find_brackets(pattern) |
|
54
|
|
|
brackets = list(map(lambda x: translate_brackets(pattern, x), brackets_index_pairs)) |
|
55
|
|
|
non_brackets_index_pair = find_non_brackets(pattern, brackets_index_pairs) |
|
56
|
|
|
print(non_brackets_index_pair) |
|
57
|
|
|
non_brackets = list(map(lambda x: translate_non_pattern(pattern, x), non_brackets_index_pair)) |
|
58
|
|
|
return ''.join(map(lambda x: x[1], sorted(non_brackets + brackets))) |
|
59
|
|
|
|
|
60
|
|
|
|
|
61
|
|
|
def unix_match(filename: str, pattern: str) -> bool: |
|
62
|
|
|
translated_pattern = translate_pattern(pattern) |
|
63
|
|
|
print(filename) |
|
64
|
|
|
print(pattern) |
|
65
|
|
|
print(translated_pattern) |
|
66
|
|
|
a = match(translated_pattern, filename) |
|
67
|
|
|
print(a) |
|
68
|
|
|
return '[]' not in pattern and bool(search(translated_pattern, filename)) |
|
69
|
|
|
|
|
70
|
|
View Code Duplication |
if __name__ == '__main__': |
|
|
|
|
|
|
71
|
|
|
print("Example:") |
|
72
|
|
|
print(unix_match('somefile.txt', '*')) |
|
73
|
|
|
|
|
74
|
|
|
# These "asserts" are used for self-checking and not for an auto-testing |
|
75
|
|
|
assert unix_match('somefile.txt', '*') == True |
|
76
|
|
|
assert unix_match('other.exe', '*') == True |
|
77
|
|
|
assert unix_match('my.exe', '*.txt') == False |
|
78
|
|
|
assert unix_match('log1.txt', 'log?.txt') == True |
|
79
|
|
|
assert unix_match('log1.txt', 'log[1234567890].txt') == True |
|
80
|
|
|
assert unix_match('log12.txt', 'log?.txt') == False |
|
81
|
|
|
assert unix_match('log12.txt', 'log??.txt') == True |
|
82
|
|
|
print("Coding complete? Click 'Check' to earn cool rewards!") |
|
83
|
|
|
|