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 首先,"/"左倾斜是正斜杠,"\" ...
随机推荐
- leetcode 566 Reshape the Matrix 重塑矩阵
参考:https://www.cnblogs.com/grandyang/p/6804753.html 注意:复习容器的定义方法?? class Solution { public: vector&l ...
- [LeetCode] Encode and Decode TinyURL 编码和解码精简URL地址
Note: This is a companion problem to the System Design problem: Design TinyURL. TinyURL is a URL sho ...
- [LeetCode] Diagonal Traverse 对角线遍历
Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal ...
- python3全栈开发-什么是粘包、粘包现象、如何解决粘包
一.粘包现象 让我们基于tcp先制作一个远程执行命令的程序(1:执行错误命令 2:执行ls 3:执行ifconfig) 注意注意注意: res=subprocess.Popen(cmd.decode( ...
- [Ioi2011]ricehub
Description 乡间有一条笔直而长的路称为“米道”.沿着这条米道上 R 块稻田,每块稻田的坐标均 为一个 1 到 L 之间(含 1 和 L)的整数.这些稻田按照坐标以不减的顺序给出,即对于 0 ...
- CSAPP-程序优化
代码移动: 如果一个表达式总是得到同样的结果,最好把它移动到循环外面,这样只需要计算一次.编译器有时候可以自动完成,比如说使用 -O1 优化.一个例子: void set_row(double *a, ...
- CSAPP-过程调用,数据存储,缓冲区溢出
程序编译: 1.预处理阶段: 1.文件包含:将#include扩展成文件正文 2.条件编译:根据#if和#ifdef将程序的某部分排除或者包含 3.宏展开:将出现宏引用的地方展开成相应的宏 2.编译阶 ...
- 【网络流】【BZOJ1070】【SCOI2007】修车
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意:问你如何分配老司机使得每部车的等待时间之和最短. 解题思路:本题不易正做,考虑 ...
- 17.10.31&11.01
10.31模拟考试 Prob.1(AC)裸的矩阵幂 Prob.2(WA)(类似括号匹配求合法方案数) 卡特兰数的一个模型运用.可以推出一个式子(推导方法一个erge讲的,一个骚猪讲的) Prob.3( ...
- [bzoj4850][Jsoi2016]灯塔
来自FallDream的博客,未经允许,请勿转载,谢谢. JSOI的国境线上有N一座连续的山峰,其中第ii座的高度是hi??.为了简单起见,我们认为这N座山峰排成了连续一条 直线.如果在第ii座山峰上 ...