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 首先,"/"左倾斜是正斜杠,"\" ...
随机推荐
- Java动态代理模式浅析
Java代理设计模式 - 静态代理 Java中的动态代理 - 调用处理器 代理设计模式的UML图: 我将首先介绍Java中的各种代理实现方法 Java代理设计模式 - 静态代理 这个例子非常简单,只有 ...
- maven引入本地jar 打jar包
没搭建私服的情况下引入本地的jar,并把本地jar打包进项目的run jar 以打包引入hadoop-common-2.7.5.jar为例 引用 复制jar包所在的路径 打开cmd命令提示符 切换路径 ...
- vue-cli 去掉严格模式:
vue-cli 去掉严格模式: 在根目录中找到 .eslintignore 文件,添加 严格模式需要监听的目录 src/*
- [TJOI 2013]拯救小矮人
Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人, ...
- 洛谷P3159 [CQOI2012]交换棋子
巧妙的拆点方式,首先把1看成黑点,0看成空的,几次交换就可以看成一条路径 1)从容量上看,这条路径为1-2-2-2-2-2----2-1 2)从费用上看,这条路径每条边费用都是1 于是用一种巧妙的拆点 ...
- hdu4729 树链剖分+二分
An Easy Problem for Elfness Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65535/65535 K (J ...
- 12563 Jin Ge Jin Qu hao
• Don’t sing a song more than once (including Jin Ge Jin Qu). • For each song of length t, either si ...
- 4999: This Problem Is Too Simple!
Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: C i x(0<=x<2^31) 表示将i节点的值改为x. Q i j x(0<=x<2^31 ...
- poj1753 高斯消元
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37055 Accepted: 16125 Descr ...
- ubuntu14.0464位 Ros环境 安装halcon13.01
至于ROS的系统,之前就是安装好的,如果有疑问的可以参考官网的安装教程,按照指令一步一步的操作,http://wiki.ros.org/cn/indigo/Installation/Ubuntu (1 ...