此 python 代码如何使用正则表达式 sub() 和 group() 将字符串转换为驼峰式大小写?

How does this python code convert string to camelCase with regex sub() and group()?

我是个新手,请放轻松:) 这是我从codewars

网上找到的一个kata的解决方案
import re
def to_camel_case(text):
    return re.sub('[_-](.)', lambda x: x.group(1).upper(), text)

我将尝试通俗易懂地介绍解决方案。

因此,首先,re.sub() 搜索指定模式 '[_-](.)' 的出现,它将匹配连字符 '-' 或下划线 '_' 紧接在另一个之前的任何子字符串特点。 re.sub() 函数然后通过匿名函数(lambda 函数)分别运行这些匹配项。

python 中的正则表达式分组本质上涉及那些大括号 () 以收集子表达式供以后在程序中使用。 lambda 函数将接受通过搜索 text 为提供的模式生成的一些正则表达式对象,然后是 return x.group(1).upper(),我们可以从正则表达式中看到,分组元素是连字符或下划线后的单个字符,这是 return 编辑并由函数替换的字符。

现在,回答你的点数:

为什么 [_-](\w+) 不起作用? 这是因为,当它找到连字符时,它会 select 后面的所有字母数字字符它,所以它将把下一个单词的全部大写。

他是如何用 sub 去掉连字符和下划线的? 这很容易回答。 re.sub() 函数替换了整个匹配项,而不仅仅是分组元素,并且在 lambda 中,他只 return 将分组元素设为大写,而不是连字符。

是否成功只将除第一个单词外的每个单词的第一个字符大写? 搜索正则表达式模式时,它正在寻找立即进行的字符 一个连字符或一个下划线,并且第一个单词不在这两个字符之前。如果您要为函数提供类似 '-hello-there' 的内容,它将产生:'HelloThere'

我以为x.group(1).upper()会把整个单词大写,怎么group(1)指的是第一个字符?这是到模式,因为模式是 '[_-](.)' 而不是 '[_-](.+)',它只匹配一个字符

我希望这对你有所帮助

所以要理解这段代码,您必须了解一些正则表达式和一些 re Python module. Let's first look at what re.sub。从文档中,函数的签名看起来像

re.sub(pattern, repl, string, count=0, flags=0)

此处重要的是 patternreplstring 参数。

  • pattern是要替换的正则表达式模式
  • repl 是您要替换匹配模式的内容,可以是字符串或以匹配对象作为参数的函数
  • string 是您希望替换操作的字符串

该函数用于查找 string 中与正则表达式 pattern 匹配的部分,并将这些部分替换为 repl

现在让我们进入使用的正则表达式:[_-](.).

  • [_-] 匹配方括号内的任何字符(_-
  • . 匹配任何字符
  • (.) 捕获 capture group
  • 中的任何字符

现在让我们把它们放在一起。完整模式将匹配两个字符。第一个字符将是 _-,第二个字符可以是任何字符。实际上,将匹配以下字符串的粗体部分。

  • 一个_two
  • 测试_3
  • 此处不匹配-
  • thiswill_Match
  • NoMatchHereEither_
  • need_more_creative_examples-

这里的重要部分是正则表达式的 (.) 部分匹配任何字符并将其存储在捕获组中,这允许我们在 repl 部分引用匹配的字符争论。

让我们来看看 repl 在这里做什么。在这种情况下,repllambda function

lambda x: x.group(1).upper()

lambda 与普通的 Python 函数并没有太大区别。您在冒号之前定义参数,然后在冒号之后定义 return 表达式。上面的 lambda 将 x 作为参数,并假定 x 是一个 match object。匹配对象有一个 group 方法,允许您引用正则表达式模式匹配的组(还记得之前的 (.) 吗?)。它获取第一个匹配的组,并使用 str 对象的内置 upper 方法将其大写。然后 returns 那个大写的字符串,这就是替换匹配的 pattern.

现在一起:

import re
def to_camel_case(text):
    return re.sub('[_-](.)', lambda x: x.group(1).upper(), text)

pattern[_-](.) 匹配任何下划线或破折号后跟任何字符。使用 repl lambda 函数捕获该字符并将其大写。 string 中与该模式匹配的部分随后将替换为该大写字符。

总而言之,我认为以上内容回答了你的大部分问题,但总结一下:

I looked up about re.sub() and group(), but I still couldn't put it together. I'm not sure how [_-](.) works, how come [_-](w+) doesn't work?

我假设您打算使用 \w 字符集,而不仅仅是 w\w 字符集匹配所有字母数字字符和下划线。如果未使用 + 运算符,此模式将起作用。 + 贪婪地匹配字符,因此它会导致捕获所有属于 \w 集的下划线或连字符后的字符。这会导致两个问题:它会将所有捕获的字符(可能是一个完整的单词)大写,并且会捕获下划线,导致后面的下划线无法被正确替换。

How did he get ride of the hyphen and underscore with sub?

repl return的函数只是第一个捕获组的大写版本。在模式 [-_](.) 中,仅捕获连字符或下划线后面的字符。实际上,模式 [-_](.) 被匹配并替换为 (.) 匹配的大写字符。这就是 hyphen/underscore 被删除的原因。

Successfully capitalize only the first char of each words except the first word? I thought x.group(1).upper() would capitalize the entire word, how come group(1) is referring to the first char?

捕获组只匹配下划线或连字符后的第一个字符,所以这是大写的。