如何理解正则表达式代码片段

4

我试图理解这段代码的作用:

passwd1=re.sub(r'^.*? --', ' -- ', line)
password=passwd1[4:]

我知道顶部的行使用正则表达式来删除“ -- ”,而底部的行也删除了一些内容?我一段时间后回到这个代码并需要改进它,但为了做到这一点,我需要再次理解它。我一直在尝试阅读正则表达式文档,但没有结果,那么正则表达式开头的r'^.*? 是什么?


1
第一行将“--”及其之前的所有内容替换为“ -- ”。第二行删除了前4个字符。这只是一个愚蠢的例子。如果第一行使用空字符串“”作为替换字符串,则不需要第二行。 - Tim Roberts
正则表达式有一个解释面板,参见 https://regex101.com/r/3jKNaU/1 - The fourth bird
3个回答

4
为了把 r'^.*? -- 拆成几个部分:
  • 在Python中字符串前的r表示这是一个正则表达式字符串,让解释器知道其为正则表达式字符串而不是一堆令人困惑的字符转义。
  • ^ 告诉正则表达式只匹配从字符串开头开始的内容。
  • .*? 匹配任意数量的字符直到...
  • --,即字面匹配。

综上所述,它将匹配任何以行首开始、到--边界的字符串。由于这是使用re.sub()函数,因此匹配到的字符串部分将被替换为--

这就是为什么像Google -- MyPassword会变成 -- MyPassword的原因。

第二行代码是一个简单的字符串切片操作,删除了字符串的前四个元素(字符)。这可能是多余的-你可以用空字符串替换匹配的部分,如下所示:

passwd1 = re.sub(r'^.* --', '', line)

这将实现相同的结果。请注意,我已经删除了?,因为*具有类似但更广泛的效果,所以它是多余的。虽然存在一些技术上的区别,但我认为您不需要知道。

?匹配前一个字符的零次或一次 - 在本例中是一个.,即“任何字符”。*将匹配前一个字符的零个或多个。.*被称为贪婪量词,而.*?则是懒惰量词。也就是说,贪婪量词会尽可能地匹配,而懒惰量词会尽可能地少匹配。在这种情况下,^.*? -- ^.* -- 之间的区别在于匹配的内容:

Something something -- mypassword -- yourpassword

在贪婪模式下,前两个子句('something something -- mypassword')被匹配并删除。在懒惰模式下,只有'something something'被删除。大多数密码不包含空格,更别说“--”了,因此您可能希望使用贪婪版本。

2
您可以使用类似 regex101 的网站输入您的正则表达式并进行分析。它会告诉您您的正则表达式是否与某些测试用例匹配,并解释正则表达式中每个字符的含义。在这种情况下,它匹配您字符串中的所有内容,直到第一个实例 ' -- ',然后将其替换为字符 ' -- '
第二行是对字符串进行切片。它获取一个子字符串,跳过前四个字符,然后继续到字符串的结尾。
实际上,给定一个包含 ' -- ' 的字符串,这一对行将获取该子字符串之后的所有内容。然而,如果在 line 中找不到该子字符串,则您将简单地丢弃前四个字符。如果 line 的长度小于四个字符,则会出现错误。

1
  • r意味着正则表达式

  • ^意味着以...开始

  • .意味着任何字符(除换行符外)

  • *意味着零个或多个出现

  • ?意味着零个或一个出现

换句话说,它匹配以确切数量的字符--开头的字符串。sub将与之匹配的字符串部分替换为' -- '

第二个命令仅设置一个变量,忽略字符串的前4个字符,这是新设置的' -- '


1
请注意,r"<a string>" 表示 Python 中的正则表达式。在 Python 中,该字符串将被视为正则表达式。但是,这并不是正则表达式的通用规范,并且可能无法移植到其他语言中。 - Nathaniel Ford
.*? 使用懒惰量词(尽可能少的字符以便匹配成功)。 - bobble bubble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接