究竟什么是"原始字符串正则表达式"以及如何使用它?

tem*_*ame 55 python regex python-module rawstring

正则表达式的python文档,关于'\'字符:

解决方案是使用Python的原始字符串表示法来表示正则表达式模式; 在前缀的字符串文字中,不以任何特殊方式处理反斜杠'r'.所以r"\n"是一个包含'\'和的双字符字符串'n',"\n"而是包含换行符的单字符字符串.通常,模式将使用此原始字符串表示法在Python代码中表示.

什么是原始字符串表示法?如果您使用原始字符串格式,这是否意味着"*"作为文字字符而不是零或多指标?这显然是不对的,否则正则表达式将彻底失去它的力量.但是,如果它是一个原始字符串,它"\n"是如何识别换行符,如果它实际上是一个反斜杠和一个"n"

我不跟随.

编辑赏金:

我试图理解原始字符串正则表达式如何匹配换行符,制表符和字符集,例如\w单词或\d数字或所有其他,如果原始字符串模式不能将反斜杠识别为普通字符以外的任何内容.我真的可以使用一些很好的例子.

Jim*_*unt 77

Zarkonnen的回答确实回答了你的问题,但没有直接回答.让我试着更直接,看看我是否可以从Zarkonnen那里获得赏金.

如果您停止使用术语"原始字符串正则表达式"和"原始字符串模式",您可能会发现这更容易理解.这些术语将两个独立的概念混为一谈:Python源代码中特定字符串的表示形式,以及字符串表示的正则表达式.

事实上,将它们视为两种不同的编程语言是有帮助的,每种编程语言都有自己的语法.Python语言具有源代码,除其他外,它构建具有特定内容的字符串,并调用正则表达式系统.正则表达式系统具有驻留在字符串对象中的源代码,并匹配字符串.两种语言都使用反斜杠作为转义字符.

首先,要理解字符串是一系列字符(即字节或Unicode代码点;这里的区别并不重要).有许多方法可以在Python源代码中表示字符串.一个原始字符串仅仅是这些表象之一.如果两个表示形成相同的字符序列,则它们会产生相同的行为.

想象一个2个字符的字符串,由反斜杠字符后跟n个字符组成.如果你知道反斜杠的字符值是92,而n是110,那么这个表达式会生成我们的字符串:

s = chr(92)+chr(110)
print len(s), s

2 \n
Run Code Online (Sandbox Code Playgroud)

传统的Python字符串表示法"\n"不会生成此字符串.相反,它会生成带有换行符的单字符字符串.在Python文档2.4.1.字符串文字说:"反斜杠(\)字符用于转义具有特殊含义的字符,例如换行符,反斜杠本身或引号字符."

s = "\n"
print len(s), s

1 
 
Run Code Online (Sandbox Code Playgroud)

(请注意,在此示例中看不到换行符,但如果仔细查看,则会在"1"后面看到一个空行.)

要获取我们的双字符字符串,我们必须使用另一个反斜杠字符来逃避原始反斜杠字符的特殊含义:

s = "\\n"
print len(s), s

2 \n
Run Code Online (Sandbox Code Playgroud)

如果要表示其中包含许多反斜杠字符的字符串,该怎么办?Python docs 2.4.1.字符串文字继续,"字符串文字可以选择以字母'r'或'R'为前缀;这样的字符串称为原始字符串,并使用不同的规则来解释反斜杠转义序列." 这是我们的双字符串,使用原始字符串表示:

s = r"\n"
print len(s), s

2 \n
Run Code Online (Sandbox Code Playgroud)

所以我们有三种不同的字符串表示形式,它们都给出相同的字符串或字符序列:

print chr(92)+chr(110) == "\\n" == r"\n"
True
Run Code Online (Sandbox Code Playgroud)

现在,让我们转向正则表达式.在Python文档,7.2.re- 正则表达式操作说:"正则表达式使用反斜杠字符('\')来表示特殊形式或允许使用特殊字符而不调用它们的特殊含义.这与Python在同一目的中使用相同字符相冲突.字符串文字......"

如果你想要一个匹配换行符的Python正则表达式对象,那么你需要一个2个字符的字符串,由反斜杠字符后跟n个字符组成.以下代码行全部设置为正则表达式对象,该对象识别换行符:

prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")
Run Code Online (Sandbox Code Playgroud)

那么为什么"通常模式将使用这种原始字符串表示法在Python代码中表示." ?因为正则表达式通常是静态字符串,可以方便地表示为字符串文字.从正则表达式包含反斜杠字符时,原始字符串是一个方便的选择.

问题

:那个表达re.compile(r"\s\tWord")怎么样?:通过将字符串与正则表达式编译分开并分别理解它们,可以更容易理解.

s = r"\s\tWord"
prog = re.compile(s)
Run Code Online (Sandbox Code Playgroud)

该字符串s包含八个字符:反斜杠,s,反斜杠,t,然后是四个字符Word.

:制表符和空格字符会发生什么变化?:在Python语言级别,字符串s没有制表符空格字符.它以四个字符开头:反斜杠,s,反斜杠,t.同时,正则表达式系统将该字符串视为正则表达式语言中的源代码,其中它表示"匹配由空格字符,制表符和四个字符组成的字符串Word.

:如果将其视为反弹和反斜杠-T,你如何匹配?:如果"你"和"那个"更加具体,那么问题就更清楚了:正则表达式系统如何匹配表达式backlash -s和backslash -t?作为"任何空白字符"和" 制表符".

:或者如果你有3个字符的字符串反斜杠-n-换行怎么办?:在Python语言中,3个字符的字符串反斜杠-n-换行符可以表示为常规字符串"\\n\n",或者原始加传统字符串r"\n" "\n",或者以其他方式表示.正则表达式系统在找到任意两个连续的换行符时匹配3个字符的字符串反斜杠-n- 换行符.

注意所有示例和文档引用都是Python 2.7.

更新:从@Vladislav Zorov和@ m.buettner的答案以及@Aerovistae的后续问题中得到澄清.

  • `ord(92)`只会引发一个`TypeError`,因为`92`不是一个字符串.你可能意味着`chr(92)`(或者可能是'unichr(92)`)? (2认同)
  • 嘿@JimDeLaHunt我想说一年后我回来读这篇文章,终于在不同的背景下理解了这个原始字符串的东西,现在我可以看到你的解释非常明确.我想当时我对它有一些巨大的心理障碍......现在我就上课了!再次感谢. (2认同)

小智 15

这些问题中的大多数都有很多单词,也许很难找到你特定问题的答案.

如果您使用常规字符串并将类似"\ t"的模式传递给RegEx解析器,Python会将该文字转换为带有选项卡字节的缓冲区(0x09).

如果您使用原始字符串并将r"\ t"这样的模式传递给RegEx解析器,则Python不会执行任何解释,并且会创建一个包含两个字节的缓冲区:'\'和't'.(0x5c,0x74).

RegEx解析器知道如何处理序列'\ t' - 它与选项卡匹配.它还知道如何处理0x09字符 - 这也与选项卡匹配.在大多数情况下,结果将无法区分.

因此,理解正在发生的事情的关键是认识到这里有两个解析器.第一个是Python解析器,它将您的字符串文字(或原始字符串文字)转换为字节序列.第二个是Python的正则表达式解析器,它将一个字节序列转换为已编译的正则表达式.


Zar*_*nen 5

使用普通字符串编写包含a的\正则表达式的问题是,您最终不得不\\为每一个编写\。因此,字符串文字"stuff\\things"r"stuff\things"产生相同的字符串。如果您想编写一个与反斜杠匹配的正则表达式,这将特别有用。

使用普通字符串,与该字符串匹配的正则表达式\"\\\\"

为什么?因为我们必须转义\两次:一次用于正则表达式语法,一次用于字符串语法。

您可以使用三引号将换行符包括在内,如下所示:

r'''stuff\
things'''
Run Code Online (Sandbox Code Playgroud)

请注意,通常,python会将\-newline视为行的延续,但是原始字符串中并非如此。另请注意,反斜杠仍然在原始字符串中转义引号,但保留在其自身中。因此,原始字符串文字r"\""会生成字符串\"。这意味着您不能以反斜杠结束原始字符串文字。

有关更多信息,请参见Python文档的词法分析部分

  • @Aerovistae:使用`r'''something <enter> onnewline'''`。“ <enter>”表示按回车键。不太漂亮,所以您可以在这里使用字符串连接吗? (2认同)
  • 实际上,由于原始字符串的处理方式,“ r” stuff \”是一个错误。 (2认同)