两个不起眼但是比较重要的设定

  • 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 字面量,正则,反斜杠和原始字符串的更多相关文章

  1. [转载]Python正则表达式匹配反斜杠'\'问题

    转载自csdnblog:Python正则表达式匹配反斜杠'\'问题 在学习Python正则式的过程中,有一个问题一直困扰我,如何去匹配一个反斜杠(即“\”)? 一.引入 在学习了Python特殊字符和 ...

  2. Python: 正则表达式匹配反斜杠 "\"

    Python正则表达式匹配反斜杠 "\" eg: >>>a='w\w\w' 'w\\w\\w' #  打印出来的 "\\" 被转义成 一个反斜 ...

  3. 【python之路38】Python正则表达式匹配反斜杠“\”

    一.引入 在学习了Python特殊字符和原始字符串之后,我觉得答案应该是这样的: 1)普通字符串:'\\'2)原始字符串:r'\'但事实上在提取诸如“3\8”反斜杠之前的数字时,我屡次碰壁,始终得不到 ...

  4. JS正则四个反斜杠的含义

    我们首先来看如下代码,在浏览器中输出的是什么? // 在浏览器中输出的 console.log('\\'); // 输出 \ console.log('\\\\'); // 输出 \\ 一:js正则直 ...

  5. python 正则表达式中反斜杠(\)的麻烦和陷阱

    这里是一点小心得:由于下面两个原因,在正则表达式中使用反斜杠就会产生了一个双重转换的问题. (1).python自身处理字符串时,反斜杠是用于转义字符 (2).正则表达式也使用反斜杠来转义字符     ...

  6. python中的反斜杠问题

    python本身使用 \ 来转义一些特殊字符,比如在字符串中加入引号的时候 s = 'i\'m superman' print(s) # i'm superman 为了防止和字符串本身的引号冲突,使用 ...

  7. 关于Python中正则表达式的反斜杠问题

    之前总是搞不明白正则表达式中的反斜杠的问题.今天经过查阅资料终于搞明白了. 其中最重要的一点就是Python自己的字符串中定义的反斜杠也是转义字符,而正则表达式中的反斜杠也是转义字符,所以正则表达式中 ...

  8. Python字符串和正则表达式中的反斜杠('\')问题

    在Python普通字符串中 在Python中,我们用'\'来转义某些普通字符,使其成为特殊字符,比如 In [1]: print('abc\ndef') # '\n'具有换行的作用 abc defg ...

  9. 【转】python中的正斜杠、反斜杠

    原文地址:http://www.cnblogs.com/followyourheart1990/p/4270566.html 首先,"/"左倾斜是正斜杠,"\" ...

随机推荐

  1. kafka知识体系-kafka设计和原理分析

    kafka设计和原理分析 kafka在1.0版本以前,官方主要定义为分布式多分区多副本的消息队列,而1.0后定义为分布式流处理平台,就是说处理传递消息外,kafka还能进行流式计算,类似Strom和S ...

  2. es6中参数【默认值,扩展运算符】

    参数默认值 1.普通参数 function info(age,name="grace"){ console.log(name); } info(); //输入:grace 2.对象 ...

  3. [LeetCode] Candy Crush 糖果消消乐

    This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...

  4. [LeetCode] Longest Palindromic Subsequence 最长回文子序列

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

  5. vue 2.0 路由切换以及组件缓存源代码重点难点分析

    摘要 关于vue 2.0源代码分析,已经有不少文档分析功能代码段比如watcher,history,vnode等,但没有一个是分析重点难点的,没有一个是分析大命题的,比如执行router.push之后 ...

  6. [C#] .NET Core/Standard 2.0 编译时报“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”错误的解决办法

    作者: zyl910 一.缘由 当创建 .NET Core/Standard 2.0项目时,VS不会像.NET Framework项目一样自动生成AssemblyInfo.cs文件. 而且,若是手工在 ...

  7. Java爬虫原理分析

    当我们需要从网络上获取资源的时候,我们一般的做法就是通过浏览器打开某个网站,然后将我们需要的东西下载或者保存下来. 但是,当我们需要大量下载的时候,这个时候通过人工一个个的去点击下载,就显得太没有效率 ...

  8. bzoj4896 补退选

    Description X是T大的一名老师,每年他都要教授许多学生基础的C++知识.在T大,每个学生在每学期的开学前都需要选课,每 次选课一共分为三个阶段:预选,正选,补退选:其中"补退选& ...

  9. [AH/HNOI2017]影魔

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂. 事实上,他吞噬的诗人灵魂早已成千上万. 千百年来,他收集了各式各样的灵魂,包括诗人. 牧师. 帝王. 乞丐. 奴隶. 罪人,当然,还有英雄. 题目描 ...

  10. 【HNOI2017】影魔

    题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个灵魂,都有着自 ...