Python进阶1 - 正则表达式: 转义字符与原始字符串详解

这边文章默认使用了富文本编辑器,请到另一篇相同内容的MarkDown编辑过的内容中查看,连接如下

Python中的转义字符与原始字符串详解


小马哥在使用正则表达式面对转义字符的时候,发现字符串的转义与正则的转义有冲突的时候,总是有些不难,但是让人感觉没规律的地方,于是就专门研究了一下,首先捋一下知识点,约定一个前提概念:

转义字符: 属于字符串的概念,作用于打印. 例如,要完成一个退格,一个制表符,一个换行,这个用字符串如何表示?

    简单,"\b,\t,\n",不过是用"\"来转义一下普通字符嘛,是的,因为b,t,n是普通字符,如果直接输出,当然就是字符,于是加上"\",打印的时候就是另一种意思了,这个打印,可以是输出到屏幕,也可以是其它输出

正则表达式中的转义: 看到这里,你会想起,正则里面好像也有转义的概念,例如,"."代表匹配字符串里面的任意字符(换行符除外),如果需要匹配真正的"."这个字符怎么办?于是我们用转义字符"\."就代表匹配字符串中的"."了.

你有没有想过这个问题,字符串中的转义和正则中的转义不是一套概念体系,如果两者没有表达上的冲突,那么相安无事,可是状况恰恰是有冲突的,"\b"在字符串中表示转义后的结果: 退格;而在正则中代表匹配目标字符串的边界. 于是就要想办法解决冲突: 定义了原始字符串来屏蔽掉冲突.

只看说明,你还是一头蒙的,那么看例子来阐述一遍上面所有的问题:

```python

# 字符串中的转义: 斜杠\代表转义字符,\b代表转义之后的字符串,是退格

data = '123\b456'

# 显示一下结果

print(data)    #发现被转义后: 12456

data = '123\n456'

print(data)    #换行: 就是通过转义符把n进行转义表示回车

```

    123456

    123

    456


如上还有\t制表符也是同样的意思,这些,都是来自于ASCII对字符的规定,记住: 这些属于字符串中的转义

下面看看正则的转义

```python

import re

print('第一次试验')

data = 'hello1 python,hello2 java'

pattern = '\bhello.'

result = re.findall(pattern,data)

print(result)

'''

分析:

这个时候的正则表达式模式,没有匹配到期望的hello1与hello2,因为\b这里代表的不是正则的边界

1,pattern = '\bhello.',首先是一个字符串,就要接受字符串的处理,

    根据ASCII表,\b是退格,是一个看不到的字符,所以'\b'是一个字符,hello是另外的字符,

2,我们期望的正则模式是: '边界hello.',这个"边界"的表示方法和字符的ASCII码冲突,没有体现出来

于是,清楚了原因,我们应该设计一个模式,在经历字符串ASCII解析后,再传递给正则引擎之后是\bhello

应该这样写: '\\bhello'

'''

print('第二次试验')

data = 'hello1 python,hello2 java'

pattern = '\\bhello.'  #这时,经过字符的ASCII表解析后,得到的字符串是'\bhello'

result = re.findall(pattern,data)

print(result)

'''

到此,你心里应该有了一个: 计算机内部针对 字符 - ->模式 的过程

不是你写了一个字符串,它就是正则的模式了,而是计算机内部要根据ASCII码进行了解析,解析的结果,拿给了正则引擎去用来搜索目标文本,

而ASCII码解析后的结果,和你期望的正则的模式发生变化了,所以正则表达式解析来的结果,不如我们期望的

'''

```

    第一次试验

    []

    第二次试验

    ['hello1', 'hello2']


如果通过上面的例子,你懂了ASCII码在暗中干了一件'见不得人'的事,如果你的脑力还够用,那么咱们再来看一个它的更有意思的事情

需求: 'python\java\go\c',解析出里面的"\",在字符概念领域,它是转义字符,在正则领域,它也是转义字符,如何操作呢?

上面,我们主要目的:让你知道,ASCII码和正则,针对转义是不同的,有冲突的,例如,\b在两者概念体系中就冲突了,

```python

import re

data = 'python\java\go\c'

'''

pattern1

这个都不用试验,肯定是错的,语法错误,解析都通不过,相当于,你想打印" ' "单引号,但是字符串的定义就是用单引号或者双引号来表示

\'相当于失去了字符串"'"的定义作用,而把"'"看做普通字符,那么这样,字符串的pattern1,就没有了字符串的结尾符了,必然错误

'''

# pattern1 = '\'  #必须注释了,语法都通不过检查

'''

pattern2

用上一个例子中分析的结果,我们用转义字符把斜杠处理过,得到就是ASCII处理后的"\",再拿去交给正则引擎,这个时候正则我们应该没问题了

的确,这里经过ASCII码处理,最终交给正则的是"\",这个时候就该正则引擎起作用了,对于它"\"也是一个转义符,可只要\这是一个不完整的转义

于是抛出error: bad escape (end of pattern) at position 0

'''

try:

    pattern2 = '\\'   

    print(pattern2)

    result2 = re.findall(pattern2,data)

    print(result2)

except Exception as e:

    print("Error: ",e)

'''

pattern3

我们应该传递给正则解析引擎一个"\\",经过正则处理,它会得到"\"这个仅仅代表字符的模式,拿着去和目标文本比对,搜索目标"\"

'\\\\'经过ASCII码处理,得到"\\",正则引擎处理'\\',得到'\'

'''

pattern3 = '\\\\'

result3 = re.findall(pattern3,data)

print(result3)

```

    \

    Error:  bad escape (end of pattern) at position 0

    ['\\', '\\', '\\']


经过上面两个例子:

例一,你应该明白了,一个字符串能作为正则的模式,中间是经过ASCII码转换的,但是为什么"\d","\w"等就相安无事呢?因为ASCII码没"整"它们;

例二,对于"\"这种比较特殊的东东,经过ASCII和正则的两次转义,语法都要正确,才能去匹配目标文本中的目标字符

有没有一种方式,不用这么麻烦,于是出现了原始字符串.

看例三,原始字符串的用法

```python

import re

data = 'python\java\go\c'

pattern = r'\\'      #这里为什么还要是两个斜杠呢? 毕竟这里是字符串的定义

print(pattern)

result = re.findall(pattern,data)

print(result)

data = 'hello1 java,hello2 python'

pattern = r'\bhello.'    #这里就去掉了\b的退格作用

print(pattern)

result = re.findall(pattern,data)

print(result)

```

    \\

    ['\\', '\\', '\\']

    \bhello.

    ['hello1', 'hello2']


可能有的同学有疑问: 为什么上面打印的result关于findall结果的地方,result列表里面都是'\\',其实'\\'代表的是一个字符'\\',print()打印这个动作就变成'\'了.不信去试试.


这边文章默认使用了富文本编辑器,请到另一篇相同内容的MarkDown编辑过的内容中查看,连接如下

Python中的转义字符与原始字符串详解

你可能感兴趣的:(Python进阶1 - 正则表达式: 转义字符与原始字符串详解)