通过 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|$)
匹配换行符或断言行尾
)
关闭非捕获组
输出
#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
和行的其余部分
)*
关闭非捕获组
例如
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
我正在尝试使用 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|$)
匹配换行符或断言行尾
)
关闭非捕获组
输出
#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
和行的其余部分
)*
关闭非捕获组
例如
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