Как получить точки с запятой кроме скобок с регулярным выражением - PullRequest
2 голосов
/ 27 февраля 2020

Для следующего C исходного кода кусок:

for (j=0; j<len; j++) a = (s) + (4); test = 5;

Я хочу вставить \n после точек с запятой ; за исключением скобок, используя python модуль регулярных выражений кода .

Для следующего C исходного кода фрагмент:

for (j=0; j<(len); (j++)) a = (s) + (4); test = 5;

Регулярное выражение ;(?![^(]*\)) работает, но не на первом фрагменте кода .

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Вам нужно считать открытые и закрытые скобки для каждого совпадения с регулярным выражением и вставлять новую строку только в том случае, если число открытых скобок больше, чем закрытых скобок. Это делается в replace (), которая вызывается при каждом совпадении регулярного выражения. Регулярное выражение ищет "(" и ")" только для подсчета и для ";" чтобы оставить его или вставить новую строку

import re

def replacement(matched_list):
    global bracket_count
    matched_char=matched_list.group(1)
    if "(" in matched_char:
        bracket_count += 1
        # don't replace, just return what was found
        return matched_char 
    elif ")" in matched_char:
        bracket_count -= 1
        # don't replace, just return what was found
        return matched_char 
    elif ";" in matched_char:
        # if we're inside brackets, insert \n
        if bracket_count == 0:
            return ';\n'
        # if not, leave it intact
        else:
            return ';'

# example 1
bracket_count=0
code="for (j=0; j<len; j++) a = (s) + (4); test = 5;"
new_code = re.sub('([();] ?)', replacement, code)
print(code)
print(new_code)

# example 2
bracket_count=0
code="for (j=0; j<(len); (j++)) a = (s) + (4); test = 5;"
new_code = re.sub('([();])', replacement, code)
print(code)
print(new_code)

# example 3
bracket_count=0
code="for (j=0; j<len; j++) test = 5; a = (s) + (4);"
new_code = re.sub('([();])', replacement, code)
print(code)
print(new_code)

Результат:

for (j=0; j<len; j++) a = (s) + (4); test = 5;
for (j=0; j<len; j++) a = (s) + (4);
test = 5;

for (j=0; j<(len); (j++)) a = (s) + (4); test = 5;
for (j=0; j<(len); (j++)) a = (s) + (4);
test = 5;
1 голос
/ 28 февраля 2020

Использовать пользовательскую функцию замены :

re.sub(pattern, repl, string, count=0, flags=0)
...
Если repl - функция, она вызывается для каждого не перекрывающееся вхождение pattern.

Функция repl вызывается для каждого вхождения одного ; и для выражений в скобках. Поскольку re.sub не находит перекрывающихся последовательностей, самая первая открывающая скобка будет запускать полное совпадение вплоть до последней закрывающей скобки.

import re

def repl(m):
    contents = m.group(1)
    if '(' in contents:
        return contents
    return ';\n'

str1 = 'for (j=0; j<len; j++) a = (s) + (4); test = 5;'
str2 = 'for (j=0; j<(len); (j++)) a = (s) + (4); test = 5;'

print (re.sub (r'(;\s*|\(.*\))', repl, str1))
print (re.sub (r'(;\s*|\(.*\))', repl, str2))

Результат:

for (j=0; j<len; j++) a = (s) + (4);
test = 5;

for (j=0; j<(len); (j++)) a = (s) + (4);
test = 5;

Миссия выполнена, для ваших (очень маленьких) выборочных данных.

Но подождите!

Небольшое, но действительное изменение в одном из примеры

str1 = 'for (j=0; j<len; j++) test = 5; a = (s) + (4);'

ломает это с неправильным выводом:

for (j=0; j<len; j++) test = 5; a = (s) + (4);

Обойти это невозможно, вам нужен конечный автомат вместо:

def state_match (text):
    parentheses = 0
    drop_space = False
    result = ''
    for character in text:
        if character == '(':
            parentheses += 1
            result += '('
        elif character == ')':
            parentheses -= 1
            result += ')'
        elif character == ' ':
            if not drop_space:
                result += ' '
            drop_space = False
        elif character == ';':
            if parentheses:
                result += character
            else:
                result += ';\n'
                drop_space = True
        else:
            result += character
    return result

str1 = 'for (j=0; j<len; j++) a = (s) + (4); test = 5;'
str2 = 'for (j=0; j<(len); (j++)) a = (s) + (4); test = 5;'
str3 = 'for (j=0; j<len; j++) test = 5; a = (s) + (4);'

print (state_match(str1))
print (state_match(str2))
print (state_match(str3))

дает правильные результаты:

for (j=0; j<len; j++) a = (s) + (4);
test = 5;

for (j=0; j<(len); (j++)) a = (s) + (4);
test = 5;

for (j=0; j<len; j++) test = 5;
a = (s) + (4);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...