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

时间:2012-10-13 07:42:52

标签: python regex python-module rawstring

regex上的python文档中,关于'\'字符:

  

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

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

我不跟随。

编辑赏金:

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

7 个答案:

答案 0 :(得分:65)

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

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

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

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

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

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

2 \n

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

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

1 
 

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

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

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

2 \n

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

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

2 \n

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

print chr(92)+chr(110) == "\\n" == r"\n"
True

现在,让我们转向正则表达式。 Python docs, 7.2. reRegular expression operations表示,"正则表达式使用反斜杠字符(' \')表示特殊表单或允许使用特殊字符而不调用其特殊含义。这与Python在字符串文字中用于相同目的的相同字符的使用相冲突..."

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

prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")

那为什么"Usually patterns will be expressed in Python code using this raw string notation."呢?因为正则表达式通常是静态字符串,可以方便地表示为字符串文字。从正则表达式包含反斜杠字符时,原始字符串是一个方便的选择。

<强>问题

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

s = r"\s\tWord"
prog = re.compile(s)

字符串s包含八个字符:反斜杠 s 反斜杠 t < / em>,然后是四个字符Word

:标签和空格字符会发生什么变化? A :在Python语言级别,字符串s没有标签空格字符。它以四个字符开头:反斜杠 s 反斜杠 t 。同时,正则表达式系统将该字符串视为正则表达式语言中的源代码,这意味着&#34;匹配由空格字符,制表符和四个字符Word组成的字符串。 / p>

:如果将其视为反弹和反斜杠-t,您如何匹配? 答案:如果“你是”这样的话,问题就更清晰了。并且&#39;那&#39;更具体:正则表达式系统如何匹配表达式backlash -s和backslash -t?作为任何空白字符&#39;以及&#39; 标签字符&#39;。

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

N.B。所有示例和文档引用都是Python 2.7。

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

答案 1 :(得分:13)

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

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

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

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

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

答案 2 :(得分:4)

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

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

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

您可以使用三引号来包含换行符,如下所示:

r'''stuff\
things'''

请注意,通常,python会将\ - 换行符视为行继续,但在原始字符串中不是这种情况。另请注意,反斜杠仍然会在原始字符串中转义引号,但它们本身就会保留。因此原始字符串文字r"\""生成字符串\"。这意味着您不能使用反斜杠结束原始字符串文字。

有关详细信息,请参阅the lexical analysis section of the Python documentation

答案 3 :(得分:3)

你似乎在努力解决RegEx不是Python的一部分,而是使用自己的解析器和编译器的不同编程语言。原始字符串可帮助您安全地将RegEx的“源代码”提供给RegEx解析器,然后RegEx解析器将为\d\w\n等字符序列分配含义...

问题的存在是因为Python和RegExps使用\作为转义字符,顺便说一下,这是巧合 - 有些语言带有其他转义字符(如换行符为“n”,但即便如此你必须在RegExps中使用“\ n”)。优点是您不需要区分这些语言中的原始字符串和非原始字符串,它们不会同时尝试转换文本和屠宰文本,因为它们会对不同的转义序列做出反应。

答案 4 :(得分:1)

相关的Python手册部分(“字符串和字节文字”)清楚地解释了原始字符串文字:

  

字符串和字节文字都可以选择以a为前缀   字母'r'或'R';这样的字符串称为原始字符串并处理   反斜杠作为文字字符。结果,在字符串文字中,   原始字符串中的'\ u'和'\ u'转义不会被特别处理。特定   Python 2.x的原始unicode文字行为与Python不同   3.x是不支持'ur'语法。

     

3.3版中的新功能:原始字节文字的'rb'前缀已经存在   添加为'br'的同义词。

     

3.3版中的新功能:支持unicode遗留文字(u'value')   被重新引入以简化双Python 2.x和。的维护   3.x代码库。有关详细信息,请参阅PEP 414.

     

在三引号字符串中,允许使用未转义的换行符和引号   (并保留),但连续三个未转义的引号除外   终止字符串。 (“引用”是用于打开的字符   字符串,即“或”。)

     

除非存在'r'或'R'前缀,否则转义字符串中的序列   根据类似于标准使用的规则解释   C.公认的逃逸序列是:

     

转义序列含义注释

     

\ newline反斜杠和换行符被忽略
  \反斜杠()
  单引号(')
  \“双引号(”)
  \ a ASCII钟(BEL)
  \ b ASCII退格(BS)
  \ f ASCII Formfeed(FF)
  \ n ASCII换行(LF)
  \ r \ n ASCII码回车(CR)
  \ t ASCII水平制表符(TAB)   \ v ASCII垂直标签(VT)
  \ ooo具有八进制值的字符ooo(1,3)
  \ xhh十六进制值为hh(2,3)

的字符      

仅在字符串文字中识别的转义序列为:

     

转义序列含义注释\ N {name}字符命名名称   Unicode数据库(4)\ uxxxx具有16位十六进制值xxxx(5)的字符   \ Uxxxxxxxx具有32位十六进制值xxxxxxxx(6)

的字符      

注意:

     
      
  1. 与标准C一样,最多可接受三位八进制数字。

  2.   
  3. 与标准C不同,只需要两个十六进制数字。

  4.   
  5. 在字节文字中,十六进制和八进制转义表示具有给定值的字节。在字符串文字中,这些转义表示a   具有给定值的Unicode字符。

  6.   
  7. 版本3.3中已更改:已添加对名称别名[1]的支持。

  8.   
  9. 可以使用此转义序列对构成代理对的一部分的各个代码单元进行编码。正好有四个十六进制数字   必需的。

  10.   
  11. 任何Unicode字符都可以这种方式编码,但基本多语种平面(BMP)之外的字符将使用   如果编译Python以使用16位代码单元(代理对),则代理对   默认)。正好需要八位十六进制数字。

  12.         

    与标准C不同,所有未识别的转义序列都保留在   字符串不变,即反斜杠保留在字符串中。 (这个   调试时行为很有用:如果转义序列输入错误,   结果输出更容易被识别为破碎。)它也是   重要的是要注意转义序列只能在字符串中识别   文字属于无法识别的字节转义类别   文字。

         

    即使在原始字符串中,也可以使用反斜杠转义字符串引号,   但反斜杠仍然在字符串中;例如,r“\”“是有效的   字符串文字由两个字符组成:反斜杠和双精度型   引用; r“\”不是有效的字符串文字(即使是原始字符串也不能   以奇数个反斜杠结束)。具体来说,是原始字符串   不能以一个反斜杠结束(因为反斜杠会逃脱   以下引用字符)。另请注意,后面会出现一个反斜杠   通过换行符被解释为这两个字符的一部分   字符串,而不是续行。

答案 5 :(得分:0)

executionsToCount = includeFreeTier ? (numExecutions - 1000000) : numExecutions; computeGBS = numExecutions * (executionTime/1000) * (allocatedMemory/1024); totalCompute = includeFreeTier ? (computeGBS - 400000) : computeGBS; requestCosts = max(executionsToCount, 0) / 1000000 * .20; executionCosts = max(totalCompute, 0) * 0.00001667; finalCost = requestCosts + executionCosts 是Python中的转义序列

\n是(Python)正则表达式中的特殊序列

他们看起来好像在同一个家庭,但他们不在。原始字符串符号将影响转义序列,但不影响正则表达式特殊序列。

有关转义序列的更多信息 搜索“ \ newline” https://docs.python.org/3/reference/lexical_analysis.html

有关特殊序列的更多信息: 搜索“ \ number” https://docs.python.org/3/library/re.html

答案 6 :(得分:0)

原始字符串不会影响python正则表达式中的特殊序列,例如\ w,\ d。它仅影响转义序列,例如\ n。因此,大多数时候我们是否在前面写r都没关系。

我认为这是大多数初学者正在寻找的答案。