举个例子:
对/etc/passwd的第20行到第25行,当指定 [*:/]+ 作为分隔符时会贪婪匹配 :*: 与 :/ 为一个间隔符,而在指定 [*:/] 作为分割符时只会分别将 :*: 匹配成3个分隔符, :/ 匹配成2个分隔符。
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj awk -F ':' '{if (NR>=20 && NR<=25) print $0}' /etc/passwd
_scsd:*:31:31:Service Configuration Service:/var/empty:/usr/bin/false
_ces:*:32:32:Certificate Enrollment Service:/var/empty:/usr/bin/false
_appstore:*:33:33:Mac App Store Service:/var/db/appstore:/usr/bin/false
_mcxalr:*:54:54:MCX AppLaunch:/var/empty:/usr/bin/false
_appleevents:*:55:55:AppleEvents Daemon:/var/empty:/usr/bin/false
_geod:*:56:56:Geo Services Daemon:/var/db/geod:/usr/bin/false
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj awk -F '[*:/]' '{if (NR>=20 && NR<=25) print $1" "$2" "$4" "$5}' /etc/passwd
_scsd 31 31
_ces 32 32
_appstore 33 33
_mcxalr 54 54
_appleevents 55 55
_geod 56 56
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj awk -F '[*:/]+' '{if (NR>=20 && NR<=25) print $1" "$2" "$4" "$5}' /etc/passwd
_scsd 31 Service Configuration Service var
_ces 32 Certificate Enrollment Service var
_appstore 33 Mac App Store Service var
_mcxalr 54 MCX AppLaunch var
_appleevents 55 AppleEvents Daemon var
_geod 56 Geo Services Daemon var
Python正则表达式re
官网介绍:https://docs.python.org/zh-cn/3/library/re.html
模式和被搜索的字符串既可以是 Unicode 字符串 (str
) ,也可以是8位字节串 (bytes
)。 但是,Unicode 字符串与 8 位字节串不能混用:也就是说,不能用字节串模式匹配 Unicode 字符串,反之亦然;同理,替换操作时,替换字符串的类型也必须与所用的模式和搜索字符串的类型一致。
正则表达式用反斜杠字符 ('\'
) 表示特殊形式,或是允许在使用特殊字符时,不引发它们的特殊含义。 这与 Python 的字符串字面值中对相同字符出于相同目的的用法产生冲突;例如,要匹配一个反斜杠字面值,用户可能必须写成 '\\\\'
来作为模式字符串,因为正则表达式必须为 \\
,而每个反斜杠在普通 Python 字符串字面值中又必须表示为 \\
。
解决办法是对于正则表达式样式使用 Python 的原始字符串表示法;在带有 'r'
前缀的字符串字面值中,反斜杠不必做任何特殊处理(直接作为字符串对象)。 因此 r"\n"
表示包含 '\'
和 'n'
两个字符的字符串,而 "\n"
则表示只包含一个换行符的字符串。 样式在 Python 代码中通常都使用原始字符串表示法。
这句话的理解:
在Shell中输入的正则表达式是“原生”的正则表达式字符串,直接当作正则表达式用,所以匹配字面的\反斜杠字符时直接输入正则表达式 '\\'
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj grep -w '\\' test.txt
\
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj cat test.txt
ab
aa
abc
\
(venv_mac) ⚙ haypin@HaypinsMBP ~/PycProj grep -w '\\' test.txt
\
而Python脚本对reg = re.compile( '\\\\' )代码行,首先按 # -*- coding: utf-8 -*- 编码进行字符串字面值——>字符串的解析,字符串字面值 '\\\\' 被解析成字符串 '\\' ,这里发生了对 \ 的转义,然后执行字符串——>正则表达式的解析,字符串 '\\' 被解析成正则表达式 r'\\' ,这里只发生了对 \ 的转义。
>>> import re
>>> reg = re.compile('\\\\')
>>> res = reg.match('\\')
>>> res.group(0)
'\\'
>>> reg2 = re.compile(r'\\')
>>> res2 = reg2.match('\\')
>>> res2.group(0)
'\\'
所以Python中正则表达式使用 reg = re.compile(r'\\'),不再进行(跳过)字符串字面值——>字符串的转义,直接将字符串字面值作为字符串,然后进行字符串——>正则表达式的转义。
Python正则表达式官方文档:
\
转义特殊字符(允许你匹配 '*'
, '?'
, 或者此类其他),或者表示一个特殊序列;特殊序列之后进行讨论。
如果你没有使用原始字符串( r'raw'
)来表达样式,要牢记Python也使用反斜杠作为转义序列;如果转义序列不被Python的分析器识别,反斜杠和字符才能出现在字符串中。如果Python可以识别这个序列,那么反斜杠就应该重复两次。这将导致理解障碍,所以高度推荐,就算是最简单的表达式,也要使用原始字符串。
re模块的正则表达式类re.Pattern的构造函数re.compile(pattern,flags)的flags默认或了re.LOCALE,从而可以根据要匹配的字符串内容的语言判断英文语境下的单词、中文语境下的单词:
>>> reg = re.compile(r'\w+')
>>> print(mystr)
张3_
>>> res = reg.search(mystr)
>>> res.group(0)
'张3_'
>>> print(mystr2)
apple_
>>> res = reg.search(mystr2)
>>> res.group(0)
'apple_'
>>> reg2 = re.compile(r'我+')
>>> mystr2 = '我我我我'
>>> res = reg2.search(mystr2)
>>> res.group(0)
'我我我我'