【问题标题】:camelCase to snake_case in sed for ill formatted python code用于格式错误的python代码的sed中的camelCase到snake_case
【发布时间】:2015-03-07 18:13:04
【问题描述】:

我有一些用camelCase编写的python代码,但根据PEP 8变量名应该用snake_case编写。我写了一个小 sed 脚本,它设法接受任何小写字母 \1,后跟一个大写字母 \2 并将其转换为 \1_ 和一个小写 \2

find . -iname \*.py | xargs sed -i "s/\([a-z]\)\([A-Z]\)/\1_\L\2/g"

但是这会将 CamelCase 变成 Camel_case。根据相同的PEP 8 标准类名应以大写字母开头的驼峰式书写。

如何编写一个不涉及 CamelCase 而是将 camelCamelCamelCamel... 转换为 camel_camel_camel_camel... 的 sed 脚本?

我有一种感觉,我达到了正则表达式的限制,因为我必须保留以小写字母开头的单词的上下文,以获得未知数量的“驼峰”。我知道我可以在另一个工具中做到这一点,但我想知道 sed 是否可以做到这一点。一个证明这是不可能的论据也足够了。

我正在使用 GNU sed 4.2.2

【问题讨论】:

  • 如果您认为不值得付出努力:pypi.python.org/pypi/autopep8
  • 不管你想做什么,已经有一个 py 包,这不是很遗憾吗?
  • @jonrsharpe 不清楚 autopep8 甚至检测到 N* 错误。你能引用一个文档或一些示例代码吗?
  • 更新:autopep8 不修复命名冲突。它使用 pep8 模块,它本身只检测这些违规行为:pep8.readthedocs.org/en/1.6.2/intro.html#error-codes。免责声明(页面顶部)明确指出不处理命名约定。

标签: python regex sed


【解决方案1】:

其中一个 cmets 提到了autopep8,这可能是 OP 的方式,但在 sed 中尝试这样做很有启发意义(我的意思是这是一个有趣的谜题)。

可以这样:

sed -r ':loop; /.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ { h; s//\1/; s/([A-Z])/_\l\1/g; G; s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)/\2\1\4/; b loop }'

代码是

:loop
/.*\<([a-z]+([A-Z][a-z]+)+)\>.*/ {
  h
  s//\1/
  s/([A-Z])/_\l\1/g
  G
  s/(.*)\n(.*)\<[a-z]+([A-Z][a-z]+)+\>(.*)/\2\1\4/
  b loop
}

这里,\&lt;[a-z]+([A-Z][a-z]+)+\&gt; 匹配 dromedaryCase 术语。 \&lt;\&gt; 是单词边界,以确保此 only 匹配此类术语。这样做,在一个循环中:

  1. 如果该行包含 dromedaryCase 术语:
  2. 将整行保存到保持缓冲区
  3. 分离 dromedaryCase 术语。这利用了// 重用了最后一个正则表达式这一事实,即 1 中的那个。
  4. 将所有大写字母替换为_,后跟对应的小写字母(这使用GNU 扩展\l;否则您需要y/ABCDEF.../abcdef.../ 命令来更改大小写)。模式空间现在包含与 dromedaryCase 术语对应的 snake_case。
  5. 将原始行从保持缓冲区附加到模式空间
  6. 在原始正则表达式的基础上,将模式空间拆分为相关部分:\1 是 snake_case 术语,\2 是替换部分之前的原行部分,\4 是 dromedaryCaseTerm 之后的部分.然后按照正确的顺序重新组装这些部件。
  7. 循环直到行中的所有 dromedaryCase 术语都被替换。

【讨论】:

  • 对我见过的最复杂的 sed 表达式进行了很好的解释。我什至不知道在 sed 中循环是可能的。 autopep8 似乎是要走的路,但我对 sed 和正则表达式的一般限制有点好奇。
  • 有证据表明 sed 是图灵完备的 here。不那么深奥的是,GNU sed 可以调用任意 shell 命令,所以...是的,功能强大。但在某些时候,您想考虑其他选择,而此时远在达到这种复杂程度之前。
【解决方案2】:

试试这个:

result = re.sub("([A-Z])", r"_\1", text, 0, re.MULTILINE)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    相关资源
    最近更新 更多