Python中的原始字符串和正则表达式
我对以下代码中的原始字符串有一些混淆:Python中的原始字符串和正则表达式,python,regex,escaping,backslash,rawstring,Python,Regex,Escaping,Backslash,Rawstring,我对以下代码中的原始字符串有一些混淆: import re text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.' text2_re = re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2) print (text2_re) #output: Today is 2012-11-27. PyCon starts 2013-3-13. print (r'(\d+)/(\d+)/(\d+)') #ou
import re
text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text2_re = re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
print (text2_re) #output: Today is 2012-11-27. PyCon starts 2013-3-13.
print (r'(\d+)/(\d+)/(\d+)') #output: (\d+)/(\d+)/(\d+)
就我对原始字符串的理解而言,如果没有r,则\被视为转义字符;使用r,反斜杠\按字面意思处理
然而,在上述代码中我无法理解的是:
在正则表达式行5中,即使存在一个r,内部的“\d”也被视为一个数字[0-9],而不是一个反斜杠\加上一个字母d
在第二个打印行8中,所有字符都被视为原始字符串
有什么区别
附加版:
我做了以下四种变化,有无r:
import re
text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text2_re = re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
text2_re1 = re.sub('(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
text2_re2 = re.sub(r'(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
text2_re3 = re.sub('(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
print (text2_re)
print (text2_re1)
print (text2_re2)
print (text2_re3)
并获得以下输出:
你能具体解释一下这四种情况吗 不是所有的
\
都会引起问题。Python有一些内置的东西,如\b
等。所以现在如果r
不存在,Python将考虑<代码> \b/COD>作为正则表达式,而不是<代码> Word边界>代码>。当它与<代码> R< /代码>模式一起使用时,代码< > \b/COD>完全保留。这是外行语言。技术上没有太多。<代码> \d>代码>在Python中不是特殊的内置,因此即使没有<代码> R>代码>模式,也将是安全的。
您可以在这里查看列表。这是python理解并将解释的列表。例如\b
,\n
而不是\d
在第一个
print
模式中,\d
解释是由正则表达式模块而不是python完成的。在第二个print
模式中,它是由python完成的。在r
模式中,它将保持原样。您必须对python解释器和re
模块进行区分
在python中,如果未绘制字符串,则后跟字符的反斜杠可以表示特殊字符。例如,\n
表示换行符,\r
表示回车,\t
表示制表符,\b
表示非破坏性的退格。python字符串中的\d
本身并不意味着任何特殊的含义
然而,在正则表达式中,有一堆字符在python中并不总是有任何意义。但问题是,“不总是”。有一件事可能会被误解,那就是\b
,在python中是一个退格,在正则表达式中是一个单词边界。这意味着,如果您将一个未经敬畏的\b
传递给正则表达式的正则表达式部分,那么在传递给正则表达式函数之前,这个\b
将被退格所取代,并且它在那里没有任何意义。因此,您必须绝对地传递带有反斜杠的b
,要做到这一点,您要么转义反斜杠,要么原始字符串
回到您关于\d
的问题,\d
在python中没有任何特殊意义,因此它没有被触及。作为正则表达式传递的相同的\d
由正则表达式引擎转换,正则表达式引擎是python解释器的独立实体
每个问题的编辑:
import re
text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text2_re = re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
text2_re1 = re.sub('(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
text2_re2 = re.sub(r'(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
text2_re3 = re.sub('(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
print(text2_re)
print(text2_re1)
print(text2_re2)
print(text2_re3)
前两个应该是直截了当的re.sub
通过匹配数字和正斜杠,并以不同的顺序替换为连字符来完成任务。由于\d
在python中没有任何特殊意义,\d
传递给re.sub
,无论表达式是否绘制
第三次和第四次出现是因为您没有为replace表达式绘制字符串\1
、\2
和\3
在python中有特殊含义,分别表示白色(或未填充的)笑脸、黑色(填充的)笑脸和心形(如果无法显示字符,则得到这些“字符框”)。因此,您不是用捕获的组替换字符串,而是用特定字符替换字符串
您会被字符串和字符串文字之间的差异弄糊涂 字符串文字是介于
“
或”
之间的文字,python解释器解析该字符串并将其放入内存。如果将字符串文字标记为原始字符串文字(使用r'
)然后,python解释器在将该字符串放入内存之前不会更改该字符串的表示形式,但一旦对它们进行了解析,它们将以完全相同的方式存储
这意味着在内存中没有原始字符串。以下两个字符串在内存中以相同的方式存储,不知道它们是否为原始字符串
r'a regex digit: \d' # a regex digit: \d
'a regex digit: \\d' # a regex digit: \d
这两个字符串都包含\d
,不能说这是来自原始字符串。因此,当您将此字符串传递到re
模块时,它会看到有一个\d
,并将其视为一个数字,因为re
模块不知道该字符串来自原始字符串文本
在您的特定示例中,要获得后跟文字d的文字反斜杠,可以使用\\d
如下所示:
import re
text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text2_re = re.sub(r'(\\d+)/(\\d+)/(\\d+)', r'\3-\1-\2', text2)
print (text2_re) #output: Today is 11/27/2012. PyCon starts 3/13/2013.
或者,在不使用原始字符串的情况下:
import re
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text_re = re.sub('(\\d+)/(\\d+)/(\\d+)', '\\3-\\1-\\2', text2)
print (text_re) #output: Today is 2012-11-27. PyCon starts 2013-3-13.
text2 = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
text2_re = re.sub('(\\\\d+)/(\\\\d+)/(\\\\d+)', '\\3-\\1-\\2', text2)
print (text2_re) #output: Today is 11/27/2012. PyCon starts 3/13/2013.
我希望这能有所帮助
编辑:我不想把事情复杂化,但因为\d
不是一个有效的转义序列,python不会更改它,所以'\d'==r'\d'
是正确的。由于\
是一个有效的转义序列,它会被更改为\
,因此您会得到'\d'='='\\d'==r'\d'
的行为。字符串会变得混乱有时唱歌
Edit2:要回答您的编辑,让我们具体看一下每一行:
text2_re = re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
re.sub
接收两个字符串(\d+)/(\d+)/(\d+)
和\3-\1-\2
。希望这能像您现在期望的那样运行
text2_re1 = re.sub('(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text2)
再次(因为\dtext2_re2 = re.sub(r'(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
\1 # stands for the ascii start-of-heading character
\2 # stands for the ascii start-of-text character
\3 # stands for the ascii end-of-text character
text2_re3 = re.sub('(\d+)/(\d+)/(\d+)', '\3-\1-\2', text2)
>>> print "\nlolwtfbbq"
lolwtfbbq
>>> print r"\nlolwtfbbq"
\nlolwtfbbq
>>>