通过 PyCharm 中的正则表达式搜索和替换操作注释掉特定的 Python 代码

Commenting out specific Python code via a regex search and replace operation in PyCharm

我正在尝试使用 PyCharm 的 'Replace in Files' 功能注释掉特定的代码。

具体来说,我希望将以下内容注释掉:

if TYPE_CHECKING:
    from foo import bar
    from x import y

所以可以替换为:

#if TYPE_CHECKING:
#    from foo import bar
#    from x import y

我需要这个,因为我正在使用 pydeps 检查循环依赖性,在撰写本文时,它似乎没有忽略 TYPE_CHECKING 保护下的导入的选项。手动注释掉这些对于我正在处理的项目来说是乏味的。

现在我正在使用这个正则表达式,它符合预期:

(^if TYPE_CHECKING:\n)(^\s+from.?)+

我正在尝试使用以下方法替换它:

##

我没想到这会奏效,因为我认为 $2 应该只匹配第二组的第一次出现。

另一种方法是简单地替换以 if TYPE_CHECKING:\s+from.+\n 开头的每一行,例如:

(^if TYPE_CHECKING:\n|^\s+from.+\n)+

然后简单地替换为。只要没有其他 'from' 导入前面有空格,这就有效。但是,这也会替换注释中出现的事件或已经注释掉的代码(我知道这可能被认为是不好的做法,但我正在寻找一种方法来使这项工作稳健地进行,无论如何)。

有没有人对方法有建议?

一个选项(如果支持)可以使用 \G 锚点。

在替换中使用 # 后跟使用 #[=16=]

的完整匹配
(?:^if TYPE_CHECKING:\R|\G(?!\A)^[^\S\r\n]*(?: from .*)?(?:\R|$))

模式匹配:

  • (?:非捕获组
    • ^if TYPE_CHECKING:\R 从行首匹配 if TYPE_CHECKING: 和一个换行符
    • |
    • \G(?!\A) 断言位置在上一个匹配的末尾,而不是在字符串的开头
    • ^[^\S\r\n]* 从行首匹配没有换行符的可选空格
    • (?: from .*)? 可选择将一行与 from 匹配(如果存在空行则交叉)
    • (?:\R|$) 匹配换行符或断言行尾
  • )关闭非捕获组

Regex demo

输出

#if TYPE_CHECKING:
#    from foo import bar
#    from x import y

使用代码的选项:

您可以匹配所有以空格和 from 开头的行,并将字符串的所有开头替换为 #。

^if TYPE_CHECKING:(?:\n\s*from .*)*

模式匹配:

  • ^ 字符串开头
  • if TYPE_CHECKING:字面匹配
  • (?:非捕获组整体重复
    • \n\s*from .* 匹配换行符,可选的空白字符,匹配 from 和行的其余部分
  • )*关闭非捕获组

Regex demo

例如

import re

pattern = r"^if TYPE_CHECKING:(?:\n\s*from .*)*"

s = ("if TYPE_CHECKING:\n"
            "    from foo import bar\n"
            "    from x import y")

res = re.sub(pattern, lambda x: re.sub(r"^", "#", x.group(), 0, re.MULTILINE), s)
print(res)

输出

#if TYPE_CHECKING:
#    from foo import bar
#    from x import y