【问题标题】:How to get semicolons except in parentheses with regex如何在正则表达式的括号中获取分号
【发布时间】:2020-06-11 19:13:23
【问题描述】:

以下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;

正则表达式;(?![^(]*\)) 有效,但不适用于第一段代码

【问题讨论】:

  • (?&lt;={)(.*?)(;) 会工作。 regex101.com/r/OBKJCr/1
  • MonkeyZeus - 谢谢,但这不起作用。我只想得到分号,不要使用括号
  • @aria 不,那个does not work
  • @aria 祝你好运,因为正则表达式无法计数,所以你无法跟踪括号是否关闭。

标签: python regex


【解决方案1】:

您需要计算每个正则表达式匹配的开括号和闭括号,如果开括号多于闭括号,则仅插入换行符。这是在replacement() 中完成的,它在正则表达式的每个匹配项上调用。正则表达式搜索“(”和“)”只是为了计数,搜索“;”离开它或插入换行符

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;

【讨论】:

  • 我会从 if 内容中删除所有 return 语句,而是在 replacement 的末尾添加一个 return matched_charbracket_count == 0 例外,因为它确实会改变输入。 repl.it/repls/VivaciousRepulsivePyramid
  • @3limin4t0r:不,“替换结束时的单个'返回匹配字符'”不会删除 ; 之后的空格正如“return ';'”所做的那样。
  • “我想在分号; 之后插入\n,但括号中使用python 代码正则表达式模块除外。” 这个问题没有说明删除空格。这些只是假设。
【解决方案2】:

使用自定义replacement function

re.sub(pattern, repl, string, count=0, flags=0)
...
如果repl 是一个函数,它会在pattern 的每个非重叠出现时调用。

函数 repl 每次出现单个 ; 时都会调用 and 用于括号表达式。由于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);

【讨论】:

    猜你喜欢
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    相关资源
    最近更新 更多