python 3.3.3 字面量,正则,反斜杠和原始字符串
两个不起眼但是比较重要的设定
- Python str类型的字面量解释器
当反斜杠及其紧接字符无法构成一个具有特殊含义的序列('recognized escape sequences')时,Python选择保留全部字符.直接看例子:
>>> '\c'
'\\c'
>>> '\d'
'\\d'
官方管'\c'这种序列叫'unrecognized escape sequences'.官方文档相应部分:
Unlike Standard C, all unrecognized escape sequences are left in the string unchanged, i.e., the backslash is left in the string. (This behavior is useful when debugging: if an escape sequence is mistyped, the resulting output is more easily recognized as broken.)
按这段英文的意思,估计C语言里面,'c'和'\c'是等同的.Python是'\\c'和'\c'等同.这个等以后学C语言再确定.
与上面对应的是,如果紧接字符能够和反斜杠构成'recognized escape sequences'的全部或者起始部分,中文就叫'被承认的转义序列'吧.比如:
>>> '\b'
'\x08'
>>> '\n'
'\n'
>>> '\x'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: truncated \xXX escape
>>> '\N'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: malformed \N character escape
>>> '\U'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: truncated \UXXXXXXXX escape
>>> '\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: truncated \uXXXX escape
- Python re模块正则表达式解释器
当反斜杠及其紧接字符无法构成一个具有特殊含义的序列(special sequences)时,re选择忽略反斜杠,例如:
>>> re.findall('\e','eee')
['e', 'e', 'e']
>>> re.findall('e','eee')
['e', 'e', 'e']
可见,'\e'和'e'起到了完全一样的效果.Python相关文档描述是:
If the ordinary character is not on the list, then the resulting RE will match the second character. For example, \$ matches the character '$'.
与上面对应的是,如果能够构成special sequences,那么re会解释为相应含义.例如:
>>> re.findall('\w','abcdefghijklmnopqrstuvwxyz')
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
字面量
字面量(Literals),是用于表示一些Python内建类型的常量的符号.最常见的字面量类型是str literals 和 bytes literals.
比如:
>>> 'abc'
'abc'
>>> "abc"
'abc'
>>> '啊哦额'
'啊哦额'
>>> b'abc'
b'abc'
>>> r'\n'
'\\n'
>>> b'啊哦额'
SyntaxError: bytes can only contain ASCII literal characters.
反斜杠\的用途按紧接其后的字符种类可划分为3类:
1.将特殊字符转换为字面量.这特殊字符包括(单引号,双引号,反斜杠):'"\
2.将普通字符转换为特殊序列.包括:abfNnrtuUvx0123456789.
(注意,bytes字面量中,NuU这三个普通字符无法被转义成特殊序列)
3.将"新行"和自身忽略掉.这个比较抽象,举例说明:py文件中,某个字符串太长了,以至于需要分两行写,那么你可以插个反斜杠,紧接着换行,然后写剩余字符串.
下面是官方文档归纳的表:
Escape Sequence | Meaning | Notes |
---|---|---|
\newline | Backslash and newline ignored | |
\\ | Backslash (\) | |
\' | Single quote (') | |
\" | Double quote (") | |
\a | ASCII Bell (BEL) | |
\b | ASCII Backspace (BS) | |
\f | ASCII Formfeed (FF) | |
\n | ASCII Linefeed (LF) | |
\r | ASCII Carriage Return (CR) | |
\t | ASCII Horizontal Tab (TAB) | |
\v | ASCII Vertical Tab (VT) | |
\ooo | Character with octal value ooo | (1,3) |
\xhh | Character with hex value hh | (2,3) |
Escape sequences only recognized in string literals are:
Escape Sequence | Meaning | Notes |
---|---|---|
\N{name} | Character named name in the Unicode database | (4) |
\uxxxx | Character with 16-bit hex value xxxx | (5) |
\Uxxxxxxxx | Character with 32-bit hex value xxxxxxxx | (6) |
举例:
>>> '\N{END OF LINE}'
'\n'
>>> '\N{HORIZONTAL TABULATION}'
'\t'
>>> '\u9f6a'=='齪'
True
>>> '\1'=='\01'
True
>>> '\1'=='\001'
True
>>> '\1'=='\0000001'
False
正则
- 正则表达式的反斜杠的作用
一种是使紧跟在后面的元字符(special characters或metacharacters)失去特殊含义,变为字面量.这些元字符有14个:
.^$*+?{}[]()\|
另一种是使紧跟在后面的普通字符变得具有特殊含义.这些普通字符是:
AbBdDsSwWZ0123456789
以及在str字面量中能被反斜杠转义的字符:
\'"abfnrtuUvx0123456789
例如:
>>> re.findall('\"','"')
['"']
正则pattern的反斜杠的作用和Python字面量的反斜杠类似,这据说是带来"反斜杠灾难"的根源.最典型的莫过于你需要用正则'\\\\'才能匹配字面量反斜杠'\\'.
为方便说明,我们假设re.search(pattern,string)中,pattern表示正则表达式字符串,string表示待匹配的字符串.
>>> re.search('\\\\','\\')
<_sre.SRE_Match object at 0x02858528>
详细来说就是一个文本层级的反斜杠'\'(比如你在txt文件中看到的反斜杠),对应Python str 字面量的'\\',对应正则pattern的'\\\\'.这个确实比较难以理解,实在不行就住这点就好:如果不是最简单的正则类型(比如'ab'),强烈推荐对pattern使用r前缀符.这样容易理解:
>>> re.search(r'\\','\\')
<_sre.SRE_Match object at 0x02858448>
注意:
- 1.多重含义的特殊序列处理机制
b0123456789比较特殊,它们在Python字面量和re正则中都能和反斜杠构成作用不同的特殊序列.例如\b,在python 字面量中解释为"退格键".re正则中解释为'单词边界'.python 字面量有优先解释权,如下可证:
>>> re.findall('\b','\b') #'\b'被优先解释为退格键,而不是单词边界
['\x08']
>>> re.findall('\\b','\b')
[]
>>> re.findall('\\b','b')
['', '']
再比如:
>>> re.findall('(a)\1\1','aaa') #\1按字面量优先解释为八进制字符串,因此无匹配结果
[]
>>> re.findall('(a)\\1\\1','aaa') #\\1按正则引擎层级的反斜杠解释为第一个匹配组提取到的字符,相当于'(a)aa'
['a']
>>> re.findall('a\1\1','a\1\1') #\1按字面量优先解释为八进制字符串,所以有匹配结果
['a\x01\x01']
了解这个设置有什么用?
1.当你想使用正则层级的特殊序列\1时,如果你没有使用r作为前缀,那么你必须使用\\1才能如愿.
2.当你想使用字面量层级的特殊序列\1时,则不能使用r作为pattern前缀.
想想,你有可能在一个r前缀的字符串中写出能够匹配值为1的八进制字符串的pattern吗?
也许我太较真了,因为实践中好像从没遇到过需要匹配值为1的八进制字符串的情况,但理论上就是这样的.
- 2.正则表达式中特殊序列的准确定义的猜想
官方文档下面的一句话值得推敲:
Note that \b is used to represent word boundaries, and means “backspace” only inside character classes
意思是说\b只有在[...]里面时才表示退格键,这显然是错的.比如下面这个例子,\b没有在[]之内,但它是按"退格键"解释的,并非"单词边界":
>>> re.findall('\b','\b')
['\x08']
除非官方文档描述的\b是指文本层面的数据(比如你在txt文档里看到的\b).
由此引出了一个猜想,re的正则pattern中"反斜杠+普通字符"构成特殊序列或"反斜杠+特殊字符"构成字面量--这种描述中的反斜杠准确来说是指两个反斜杠!
仍然是举例说明:
>>> re.findall('\\b\w+\\b','one two three') #必须用\\b才能表示单词边界
['one', 'two', 'three']
>>> re.findall('\\b\\w+\\b','one two three') #想想,为什么\w和\\w都一样
['one', 'two', 'three']
>>> re.findall('\d','')
['', '', '']
>>> re.findall('\\d','')
['', '', '']
- 3.u和U只在str字面量中才能被转义,bytes字面量中是普通字符.
以下是我猜测的正则表达式分析器和Python字面量分析器的传递规则表格:
Python string literal | values passed to regular expression | number of characters | what regular expression engine does | real meaning for regular expression |
\e | \e | 2 | ignore the backslash | e |
\\e | \e | 2 | ignore the backslash | e |
e | e | 1 | nothing spacial | e |
\n | \n | 1 | nothing spacial | 换行符 |
\\n | \n | 2 | \n is special | 换行符 |
\b | \b | 1 | nothing spacial | 退格键 |
\\b | \b | 2 | \b is special | word boundary |
\s | \s | 2 | \s is special | Unicode whitespace characters |
\\ | \ | 1 | must followed by a charcter | Can't form any meaning |
\\\\ | \\ | 2 | remove all special meanning of \ | \ |
* | * | 1 | * is special | repeat the left characters 0 or more times |
\* | \* | 2 | remove all special meanning of * | * |
最后是待探究的例子:
>>> re.findall('\n','\n\n')
['\n', '\n']
>>> re.findall('\\n','\n\n')
['\n', '\n']
>>> re.findall('\\\n','\n\n')
['\n', '\n']
>>> re.findall('\\\\n','\n\n')
[]
>>> re.findall('\b','\b\b')
['\x08', '\x08']
>>> re.findall('\\b','\b\b')
[]
>>> re.findall('\\\b','\b\b')
['\x08', '\x08']
>>> re.findall('\\\\b','\b\b')
[]
>>> re.findall('\c','\c\c')
['c', 'c']
>>> re.findall('\\c','\c\c')
['c', 'c']
>>> re.findall('\\\c','\c\c')
['\\c', '\\c']
>>> re.findall('\\\\c','\c\c')
['\\c', '\\c']
参考:
Python 3.3.3 官方文档
python 3.3.3 字面量,正则,反斜杠和原始字符串的更多相关文章
- [转载]Python正则表达式匹配反斜杠'\'问题
转载自csdnblog:Python正则表达式匹配反斜杠'\'问题 在学习Python正则式的过程中,有一个问题一直困扰我,如何去匹配一个反斜杠(即“\”)? 一.引入 在学习了Python特殊字符和 ...
- Python: 正则表达式匹配反斜杠 "\"
Python正则表达式匹配反斜杠 "\" eg: >>>a='w\w\w' 'w\\w\\w' # 打印出来的 "\\" 被转义成 一个反斜 ...
- 【python之路38】Python正则表达式匹配反斜杠“\”
一.引入 在学习了Python特殊字符和原始字符串之后,我觉得答案应该是这样的: 1)普通字符串:'\\'2)原始字符串:r'\'但事实上在提取诸如“3\8”反斜杠之前的数字时,我屡次碰壁,始终得不到 ...
- JS正则四个反斜杠的含义
我们首先来看如下代码,在浏览器中输出的是什么? // 在浏览器中输出的 console.log('\\'); // 输出 \ console.log('\\\\'); // 输出 \\ 一:js正则直 ...
- python 正则表达式中反斜杠(\)的麻烦和陷阱
这里是一点小心得:由于下面两个原因,在正则表达式中使用反斜杠就会产生了一个双重转换的问题. (1).python自身处理字符串时,反斜杠是用于转义字符 (2).正则表达式也使用反斜杠来转义字符 ...
- python中的反斜杠问题
python本身使用 \ 来转义一些特殊字符,比如在字符串中加入引号的时候 s = 'i\'m superman' print(s) # i'm superman 为了防止和字符串本身的引号冲突,使用 ...
- 关于Python中正则表达式的反斜杠问题
之前总是搞不明白正则表达式中的反斜杠的问题.今天经过查阅资料终于搞明白了. 其中最重要的一点就是Python自己的字符串中定义的反斜杠也是转义字符,而正则表达式中的反斜杠也是转义字符,所以正则表达式中 ...
- Python字符串和正则表达式中的反斜杠('\')问题
在Python普通字符串中 在Python中,我们用'\'来转义某些普通字符,使其成为特殊字符,比如 In [1]: print('abc\ndef') # '\n'具有换行的作用 abc defg ...
- 【转】python中的正斜杠、反斜杠
原文地址:http://www.cnblogs.com/followyourheart1990/p/4270566.html 首先,"/"左倾斜是正斜杠,"\" ...
随机推荐
- 机器学习基石:08 Noise and Error
噪声:误标.对同一数据点的标注不一致.数据点信息不准确...... 噪声是针对整个输入空间的. 存在噪声的情况下,VC bound依旧有用: 存在噪声,就是f------>p(y|x),f是p的 ...
- HttpClient入门二
通过上一节我们已经可以实现对一个网站源码的抓取. 但是,有一些网站,在爬取的时候会出现如下的错误: HTTP/1.1 503 Service Unavailable <!DOCTYPE html ...
- 洛谷P3168 [CQOI2015]任务查询系统
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...
- NOIP 2015
Prob.1 2015 神奇的幻方 模拟就好了.(这不是noip2017的初赛题么.)代码: #include<cstdio> #include<cstring> #inclu ...
- Codeforces #Round 406(Div.2)
来自FallDream的博客,未经允许,请勿转载,谢谢. ------------------------------------------------------- 大家好,我是一个假人.在学习O ...
- udacity/CarND-Path-Planning-Project 工程详细配置过程——吐血整理
本人原创,转载请注明地址 学习udacity/CarND-Path-Planning-Project 工程过程 1.首先登陆 jeremy-shannon/CarND-Path-Planning-Pr ...
- fatal error LNK1104: 无法打开文件“lua51.lib”
今天学习C++与Lua通信,遇到了问题:fatal error LNK1104: 无法打开文件"lua51.lib" 开发环境: VS2012 cocos版本:cocos2d-x- ...
- Linux学习之CentOS(十五)----磁盘管理之 启动挂载(转)
启动挂载 /etc/fstab 及 /etc/mtab 刚刚上面说了许多,那么可不可以在启动的时候就将我要的文件系统都挂好呢?这样我就不需要每次进入 Linux 系统都还要在挂载一次呀!当然可以啰!那 ...
- 9.QT-标准对话框
Qt提供的可复用的标准对话框,全部继承自QDialog类,如下图所示: QMessageBox:信息对话框,用于显示信息.询问问题等: QFileDialog:文件对话框 QColorDialog:颜 ...
- [原创]手把手教你写网络爬虫(7):URL去重
手把手教你写网络爬虫(7) 作者:拓海 摘要:从零开始写爬虫,初学者的速成指南! 封面: 本期我们来聊聊URL去重那些事儿.以前我们曾使用Python的字典来保存抓取过的URL,目的是将重复抓取的UR ...