对于格式不正确的 python 代码,在 sed 中将驼峰式命名为 snake_case
camelCase to snake_case in sed for ill formatted python code
我有一些 python 代码是用驼峰命名法写的,但是根据 PEP 8 变量名应该写成 snake_case。我写了一个小的 sed 脚本,它设法接受任何小写字母 \1,然后是大写字母 \2,然后将其变成 \1_ 和小写字母 \2
find . -iname \*.py | xargs sed -i "s/\([a-z]\)\([A-Z]\)/_\L/g"
但是这会将 CamelCase 变成 Camel_case。根据相同的 PEP 8 标准 class 名称应以大写字母开头的 CamelCase 书写。
我如何编写一个不使用 CamelCase 而是将 camelCamelCamelCamelCamel... 翻译成 camel_camel_camel_camel...[=28 的 sed 脚本=]?
我感觉我正在达到正则表达式的极限,因为我必须在未知数量的 "camel humps" 中保持以小写字母开头的单词的上下文。我知道我可以在另一个工具中做到这一点,但我想知道 sed 是否可以做到这一点。对此不可能的论证也足够了。
我正在使用 GNU sed 4.2.2
试试这个:
result = re.sub("([A-Z])", r"_", text, 0, re.MULTILINE)
其中一条评论提到 autopep8,这可能是选择 OP 的方式,但在 sed 中尝试这样做很有启发意义(我的意思是这是一个有趣的谜题)。
这是可能的:
sed -r ':loop; /.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ { h; s///; s/([A-Z])/_\l/g; G; s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)//; b loop }'
密码是
:loop
/.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ {
h
s///
s/([A-Z])/_\l/g
G
s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)//
b loop
}
这里,\<[a-z]+([A-Z][a-z]+)+\>
匹配一个 dromedaryCase 术语。 \<
和\>
是词界,保证这个只匹配这样的词。所以这是一个循环:
- 如果该行包含 dromedaryCase 术语:
- 将整行保存到保持缓冲区
- 分离 dromedaryCase 术语。这利用了
//
重用最后一个正则表达式这一事实,即来自 1. 的正则表达式
- 将所有大写字母替换为
_
,然后是对应的小写字母(这使用 GNU 扩展 \l
;否则您需要 y/ABCDEF.../abcdef.../
命令来更改案件)。模式 space 现在包含与 dromedaryCase 术语对应的 snake_case。
- 将保留缓冲区中的原始行附加到模式 space
- 在原始正则表达式的基础上,将模式 space 拆分为相关部分:
</code> 是 snake_case 项,<code>
是原始行的一部分在替换部分之前,
是dromedaryCaseTerm之后的部分。然后按照正确的顺序重新组装这些零件。
- 循环直到替换行中的所有 dromedaryCase 术语。
我有一些 python 代码是用驼峰命名法写的,但是根据 PEP 8 变量名应该写成 snake_case。我写了一个小的 sed 脚本,它设法接受任何小写字母 \1,然后是大写字母 \2,然后将其变成 \1_ 和小写字母 \2
find . -iname \*.py | xargs sed -i "s/\([a-z]\)\([A-Z]\)/_\L/g"
但是这会将 CamelCase 变成 Camel_case。根据相同的 PEP 8 标准 class 名称应以大写字母开头的 CamelCase 书写。
我如何编写一个不使用 CamelCase 而是将 camelCamelCamelCamelCamel... 翻译成 camel_camel_camel_camel...[=28 的 sed 脚本=]?
我感觉我正在达到正则表达式的极限,因为我必须在未知数量的 "camel humps" 中保持以小写字母开头的单词的上下文。我知道我可以在另一个工具中做到这一点,但我想知道 sed 是否可以做到这一点。对此不可能的论证也足够了。
我正在使用 GNU sed 4.2.2
试试这个:
result = re.sub("([A-Z])", r"_", text, 0, re.MULTILINE)
其中一条评论提到 autopep8,这可能是选择 OP 的方式,但在 sed 中尝试这样做很有启发意义(我的意思是这是一个有趣的谜题)。
这是可能的:
sed -r ':loop; /.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ { h; s///; s/([A-Z])/_\l/g; G; s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)//; b loop }'
密码是
:loop
/.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ {
h
s///
s/([A-Z])/_\l/g
G
s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)//
b loop
}
这里,\<[a-z]+([A-Z][a-z]+)+\>
匹配一个 dromedaryCase 术语。 \<
和\>
是词界,保证这个只匹配这样的词。所以这是一个循环:
- 如果该行包含 dromedaryCase 术语:
- 将整行保存到保持缓冲区
- 分离 dromedaryCase 术语。这利用了
//
重用最后一个正则表达式这一事实,即来自 1. 的正则表达式
- 将所有大写字母替换为
_
,然后是对应的小写字母(这使用 GNU 扩展\l
;否则您需要y/ABCDEF.../abcdef.../
命令来更改案件)。模式 space 现在包含与 dromedaryCase 术语对应的 snake_case。 - 将保留缓冲区中的原始行附加到模式 space
- 在原始正则表达式的基础上,将模式 space 拆分为相关部分:
</code> 是 snake_case 项,<code>
是原始行的一部分在替换部分之前,是dromedaryCaseTerm之后的部分。然后按照正确的顺序重新组装这些零件。
- 循环直到替换行中的所有 dromedaryCase 术语。