자체 매칭 정규 표현식 [닫기]


15

자신과 일치하는 사소한 정규식을 작성하십시오.

예를 들어, #.*$줄 끝까지 파이썬에서 문자열 외부의 주석을 일치시키고 펄 정규식 구문에서도 일치합니다.

규칙 :

  • 정규식은 유용하거나 실용적인 것을 수행해야합니다.
  • 사용중인 정규식 구문을 알려주십시오 (예 : perl 또는 POSIX).
  • 우승자는 가장 높은 투표 준수 답변입니다.
  • 창의력을 발휘하십시오!

6
유효한 정규 표현식과 일치하는 정규 표현식이 있는지 여부에 대해 얼마 전에 SO에 대한 질문이있었습니다 : stackoverflow.com/questions/172303/…
Patrick Oscity

5
사소한 것을 정의하십시오. 내 말은, A사소한 일이지만 선을 어디로 그리나요? 그리고 "self-matching"은 자신과 일치하거나 다른 문자열과도 일치 할 수 있다는 것을 의미 합니까? 겠습니까 .자격?
Mr Lister

1
정규 표현식을 설명하는 문법에 컨텍스트가 없기 때문에 실제로 정규 표현식이 아닌 @padde입니다.
FUZxxl

1
@FUZxxl 예, 사실이지만 다른 정규 표현식과 일치하는 정규 표현식을 작성할 수는 있지만 일치하는 정규 표현식의 유효성은 신경 쓰지 않습니다.
Patrick Oscity

1
@padde 그렇다면 잘못된 정규 표현식은 무엇입니까? 유효하지 않은 정규 표현식은 분명히 정규 표현식이 아닙니다. 따라서 당신은 본질적으로 다음과 같이 말합니다. "그렇습니다.하지만 다른 정규식과 일치하는 정규식을 작성할 수는 있지만 일치하는 정규식이 실제로 정규식인지 신경 쓰지 않습니다"(sic!)
FUZxxl

답변:



11

피톤

아래는 자체 매칭 정규식 생성기입니다. 당신은 두 개의 목록을 제공, 하나는 다른 하나는 정규식해야 데이터 훈련을 포함, 정규식 (자신을 일치 이외에)과 일치해야 훈련 데이터를 포함 하지 일치를 :

from random import choice, randrange
import re
from itertools import zip_longest, chain, islice
from operator import itemgetter

CHAR_SET = [chr(i) for i in range(128)] + [r"\\", r"\d", r"\D",
                                           r"\w", r"\W", r"\s",
                                           r"\S", r"?:", r"\1",
                                           r"\2", r"\A", r"\b",
                                           r"\B", r"\Z", r"\.",
                                           r"\[", r"\]", r"\(",
                                           r"\)", r"\{", r"\}",
                                           r"\+", r"\|", r"\?",
                                           r"\*"]

CHAR_SAMPLE = []
BREAKPOINT = re.compile(
    r"""
    \(.*?\)|
    \[.*?\]|
    \{.*?\}|
    \w+(?=[\(\[\{])?|
    \S+?|
    \.\*\??|
    \.\+\??|
    \.\?\??|
    \\.|
    .*?
    """,
    re.VERBOSE)

MATCH_BRACKETS = {'(': ')', '[': ']', '{': '}'}
CLOSE_BRACKETS = {')', ']', '}'}
REGEX_SEEDER = [
    r".*?",
    r"(?:.*?)",
    r"\w|\s",
    r"(?<.*?)",
    r"(?=.*?)",
    r"(?!.*?)",
    r"(?<=.*?)",
    r"(?<!.*?)",
    ]

LEN_LIMIT = 100

def distribute(distribution):
    global CHAR_SAMPLE
    for item in CHAR_SET:
        if item in distribution:
            CHAR_SAMPLE.extend([item] * distribution[item])
        else:
            CHAR_SAMPLE.append(item)

def rand_index(seq, stop=None):
    if stop is None:
        stop = len(seq)
    try:
        return randrange(0, stop)
    except ValueError:
        return 0

def rand_slice(seq):
    try:
        start = randrange(0, len(seq))
        stop = randrange(start, len(seq))
        return slice(start, stop)
    except ValueError:
        return slice(0,  0)


#Mutation Functions

def replace(seq):
    seq[rand_index(seq)] = choice(CHAR_SAMPLE)

def delete(seq):
    del seq[rand_index(seq)]

def insert(seq):
    seq.insert(rand_index(seq, len(seq) + 1), choice(CHAR_SAMPLE))

def duplicate(seq):
    source = rand_slice(seq)
    seq[source.stop: source.stop] = seq[source]

def swap(seq):
    if len(seq) < 2: return
    a = rand_index(seq, len(seq) - 1)
    seq[a], seq[a + 1] = seq[a + 1], seq[a]

dummy = lambda seq: None

MUTATE = (
    replace,
    delete,
    insert,
    duplicate,
    swap,
    dummy,
    dummy,
    )

def repair_brackets(seq):
    """Attempts to lower the percentage of invalid regexes by
    matching orphaned brackets"""

    p_stack, new_seq = [], []
    for item in seq:
        if item in MATCH_BRACKETS:
            p_stack.append(item)
        elif item in CLOSE_BRACKETS:
            while p_stack and MATCH_BRACKETS[p_stack[-1]] != item:
                new_seq.append(MATCH_BRACKETS[p_stack[-1]])
                p_stack.pop()
            if not p_stack:
                continue
            else:
                p_stack.pop()
        new_seq.append(item)
    while p_stack:
        new_seq.append(MATCH_BRACKETS[p_stack.pop()])
    return new_seq

def compress(seq):
    new_seq = [seq[0]]
    last_match = seq[0]
    repeat = 1
    for item in islice(seq, 1, len(seq)):
        if item == last_match:
            repeat += 1
        else:
            if repeat > 1:
                new_seq.extend(list("{{{0}}}".format(repeat)))
            new_seq.append(item)
            last_match = item
            repeat = 1
    else:
        if repeat > 1:
            new_seq.extend(list("{{{0}}}".format(repeat)))
    return new_seq


def mutate(seq):
    """Random in-place mutation of sequence"""
    if len(seq) > LEN_LIMIT:
        seq[:] = seq[:LEN_LIMIT]
    c = choice(MUTATE)
    c(seq)

def crossover(seqA, seqB):
    """Recombination of two sequences at optimal breakpoints
    along each regex strand"""

    bpA = [item.start() for item in BREAKPOINT.finditer(''.join(seqA))]
    bpB = [item.start() for item in BREAKPOINT.finditer(''.join(seqA))]
    slObjA = (slice(*item) for item in zip(bpA, bpA[1:]))
    slObjB = (slice(*item) for item in zip(bpB, bpB[1:]))
    slices = zip_longest(
        (seqA[item] for item in slObjA),
        (seqB[item] for item in slObjB),
        fillvalue=[]
        )
    recombinant = (choice(item) for item in slices)
    return list(chain.from_iterable(recombinant))

#Fitness testing

def match_percentage(match):
    """Calculates the percentage a text actually matched
    by a regular expression"""

    if match and match.endpos:
        return (match.end() - match.start()) / match.endpos
    else:
        return 0.001

def fitness_test(seq, pos_matches, neg_matches):
    """Scoring algorithm to determine regex fitness"""

    try:
        self_str = ''.join(seq)
        regex = re.compile(self_str)
    except (re.error, IndexError):
        seq[:] = repair_brackets(seq)
        try:
            self_str = ''.join(seq)
            regex = re.compile(self_str)
        except (re.error, IndexError):
            return 0.001

    pos_score = sum(match_percentage(regex.search(item))
                    for item in pos_matches) / len(pos_matches) / 3

    neg_score = (1 - sum(match_percentage(regex.search(item))
                    for item in neg_matches) / len(neg_matches)) / 3

    self_score = match_percentage(regex.search(self_str)) / 3

    return pos_score + self_score + neg_score

#Population Management

def generate_pop(pos_matches, neg_matches, pop_size):
    sources = (pos_matches, REGEX_SEEDER)
    return [crossover(
        choice(choice(sources)), choice(choice(sources))
        ) for i in range(pop_size)]

def glean_pop(population, cutoff, fit_test, ft_args=()):
    scores = (fit_test(bug, *ft_args) for bug in population)
    ranked = sorted(zip(population, scores), key=itemgetter(1), reverse=True)
    maxItem = ranked[0]
    new_pop = next(zip(*ranked))[:cutoff]
    return maxItem, new_pop

def repopulate(population, pop_size):
    cutoff = len(population)
    for i in range(pop_size // cutoff):
        population.extend([crossover(choice(population), choice(population))
                           for i in range(cutoff)])
    population.extend([population[i][:] for i in range(pop_size - len(population))])

#Simulator
def simulate(pos_matches, neg_matches, pop_size=50, cutoff=10, threshold=1.0):
    population = generate_pop(pos_matches, neg_matches, pop_size)
    while True:
        for bug in population:
            mutate(bug)

        #Scoring step
        max_item, population = glean_pop(
            population,
            cutoff,
            fitness_test,
            (pos_matches, neg_matches)
            )

        #Exit condition:
        max_regex, max_score = max_item
        if max_score >= threshold:
            return max_score, max_regex
        """
        print(max_score, ''.join(max_regex))
        input("next?")"""

        #Repopulation Step:
        population = list(population)
        repopulate(population, pop_size)

1
이거 파이썬인가요?
Griffin

1
@JoelCornett 내 자신의 simulate함수를 작성 하는 것이 사용법의 일부입니까? 당신의 simulate함수는 인수 2를 사용하지 않습니다.
Casey Kuball

1
@Darthfett : 아니요. 함수 호출 방법의 예입니다. 나는 (가설적인) 내용을 설명하는 변수 이름을 사용했습니다. 매개 변수 2에 대한 나의 실수는 오타였습니다. no_match이름이 바뀌어야합니다 no_match_list. 편집
Joel Cornett

1
왜 호출 population = generate_pop(pos_matches, neg_matches, pop_size)하지만 generate_pop함수는 절대 neg_matches매개 변수를 사용하지 않습니까? 또한 함수를 호출하는 예제를 포함시킬 수 있습니까? 내가 그렇게 부를 수 있을까 simulate(["Hello","World","world"], ["woah","bad","dont match"])?
mbomb007

1
이봐, 내가 쓴지 몇 년이 지났어. 테스트하지 않고 코드를 읽는 것만 simulate()으로도 설명대로 함수를 호출 할 수 있습니다 . 그리고 네, 그렇습니다. 초기 인구를 생성하기 위해 부정적인 데이터를 사용하지 않습니다.
Joel Cornett

5

비슷한 것들과 일치하는 JavaScript 정규 표현식.

/^\/\^\\\/\\\^[\\\[\]\/\^\${},\dd]{34}$/

다음과 같이 테스트 할 수 있습니다.

(function test() {
    var re =/^\/\^\\\/\\\^[\\\[\]\/\^\${},\dd]{34}$/;
    var m  =/=([^;]+)/.exec(test)[1];
    return re.exec(m);
})();

1
"같은 것"이란 무엇입니까? 이것이 실용적이거나 어떤 식 으로든 유용합니까?
케이시 쿠볼

2
@Darthfett : 자신과이 정규 표현식을 일치시키려는 유사한 정규 표현식과 일치합니다. 아니요, 어떤 식 으로든 실용적이지 않거나 유용하지는 않지만 가능한 실용적이거나 유용하지만 흥미롭고 흥미로운 정규식은 정규식과 일치하는 정규식입니다. 무슨 짓을했는지
Ry-
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.