连同注释一起去掉注释之间的部分字符串

Remove part of the string between the comments along with the comments

这是一个字符串。我想删除带有注释本身的 C 风格注释。 不使用正则表达式

a = "word234 /*12aaa12*/"

我希望输出只是:

word234

这里有一个简单的算法,可以将状态保持在 2 个字符以上,并使用标志来保留或不保留这些字符。

a = "word234 /*12aaa12*/ word123 /*xx*xx*/ end"

out = []
add = True
prev = None
for c in a:
    if c == '*' and prev == '/':
        if add:
            del out[-1]
        add = False
    if c == '/' and prev == '*':
        add = True
        prev = c
        continue
    prev = c
    if add:
        out.append(c)
s2 = ''.join(out)
print(s2)

输出:

word234  word123  end

如果你想处理嵌套评论(不确定这是否存在,但这很有趣),算法很容易修改为使用计算深度级别的标志:

a = "word234 /*12aaa12*/ word123 /*xx/*yy*/xx*/ end"

out = []
lvl = 0
prev = None
for c in a:
    if c == '*' and prev == '/':
        if lvl == 0:
            del out[-1]
        lvl -= 1
    if c == '/' and prev == '*':
        lvl += 1
        prev = c
        continue
    prev = c
    if lvl == 0:
        out.append(c)
s2 = ''.join(out)
print(s2)

您可以使用 str.find 搜索字符串中出现的 /**/

str.find returns /**/ 的索引。 str.find returns -1 如果在字符串中找不到 /*。我们可以将其用作循环中的停止条件,搜索下一条评论,直到没有评论为止。

然后,我们可以使用这些索引和 str.join 将所有 non-comment 个子字符串连接成一个字符串。

def indices_c_comments(s):
    yield 0
    i = s.find('/*')
    while i != -1:
        j = s.find('*/', i)
        yield from (i, j+2)
        i = s.find('/*', j)
    yield len(s)

def strip_c_comments(s):
    g = indices_c_comments(s)
    return ''.join(s[i:j] for i,j in zip(g, g))

for s in ('text/*comment*/text/*comment*/text', 'text/*comment*//*comment*/text', 'text/*comment*/', '/*comment*/'):
    print('"{}"  -->  "{}"'.format(s, strip_c_comments(s)))
# "text/*comment*/text/*comment*/text"  -->  "texttexttext"
# "text/*comment*//*comment*/text"  -->  "texttext"
# "text/*comment*/"  -->  "text"
# "/*comment*/"  -->  ""

增强来自@mozway 的建议答案:

(出于演示目的,条件比必要的更明确。)

def remove_comments(s, start_tok='/*', end_tok='*/', nested=True, raise_on_imbalance=True):
    lvl    = 0
    output = ""
    i      = 0
    while i < len(s):
        start_len_chs = s[i:i+len(start_tok)]
        end_len_chs   = s[i:i+len(end_tok)]
        if start_len_chs == start_tok and nested:
            lvl += 1
            i += len(start_tok)
        elif start_len_chs == start_tok and not nested and lvl == 0:
            lvl = 1
            i += len(start_tok)
        elif start_len_chs == start_tok and not nested and lvl != 0:
            output += start_len_chs
            i += len(start_tok)
        elif end_len_chs == end_tok and nested:
            lvl -= 1
            i += len(end_tok)
        elif end_len_chs == end_tok and not nested and lvl != 0:
            lvl = 0
            i += len(end_tok)
        elif end_len_chs == end_tok and not nested and lvl == 0:
            output += end_len_chs
            i += len(end_tok)
        elif lvl == 0:
            output += s[i]
            i += 1
        else:
            i += 1
    if raise_on_imbalance and (start_tok in output or end_tok in output):
        raise ValueError("Imbalanced comment tokens")
    return output

你真的应该自己尝试一下。如果您不理解所提供答案中发生的事情,那么您将一无所获。