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 首先,"/"左倾斜是正斜杠,"\" ...
随机推荐
- kafka知识体系-kafka设计和原理分析
kafka设计和原理分析 kafka在1.0版本以前,官方主要定义为分布式多分区多副本的消息队列,而1.0后定义为分布式流处理平台,就是说处理传递消息外,kafka还能进行流式计算,类似Strom和S ...
- es6中参数【默认值,扩展运算符】
参数默认值 1.普通参数 function info(age,name="grace"){ console.log(name); } info(); //输入:grace 2.对象 ...
- [LeetCode] Candy Crush 糖果消消乐
This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...
- [LeetCode] Longest Palindromic Subsequence 最长回文子序列
Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...
- vue 2.0 路由切换以及组件缓存源代码重点难点分析
摘要 关于vue 2.0源代码分析,已经有不少文档分析功能代码段比如watcher,history,vnode等,但没有一个是分析重点难点的,没有一个是分析大命题的,比如执行router.push之后 ...
- [C#] .NET Core/Standard 2.0 编译时报“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”错误的解决办法
作者: zyl910 一.缘由 当创建 .NET Core/Standard 2.0项目时,VS不会像.NET Framework项目一样自动生成AssemblyInfo.cs文件. 而且,若是手工在 ...
- Java爬虫原理分析
当我们需要从网络上获取资源的时候,我们一般的做法就是通过浏览器打开某个网站,然后将我们需要的东西下载或者保存下来. 但是,当我们需要大量下载的时候,这个时候通过人工一个个的去点击下载,就显得太没有效率 ...
- bzoj4896 补退选
Description X是T大的一名老师,每年他都要教授许多学生基础的C++知识.在T大,每个学生在每学期的开学前都需要选课,每 次选课一共分为三个阶段:预选,正选,补退选:其中"补退选& ...
- [AH/HNOI2017]影魔
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂. 事实上,他吞噬的诗人灵魂早已成千上万. 千百年来,他收集了各式各样的灵魂,包括诗人. 牧师. 帝王. 乞丐. 奴隶. 罪人,当然,还有英雄. 题目描 ...
- 【HNOI2017】影魔
题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个灵魂,都有着自 ...