替换字符串带斜杠_python字符串零碎总结
本⽂讲⼀讲与python字符串打交道时的⼀些注意事项,最初是参考python cookbook⼀书,后来更新了⼀部分内容。⽬录如下
尽量使⽤字符串⽅法⽽不是re库
正则表达式中实现“或”的逻辑(2020年9⽉7⽇更新了多字符的或逻辑)
字符串拼接
⽂件读写时
配合⽣成器使⽤
字符串反斜杠和正则(2020年9⽉7⽇更新新增了这⼀节)
python 正则表达式技巧(2020年12⽉10⽇更新)
1.尽量使⽤字符串⽅法⽽不是re库
我平常操作字符串时最常⽤的是join strip split +这⼏个⽅法,如果遇到这⼏个⽅法解决不了的事情就去使⽤re库,如字符串匹配、替换等,甚⾄都完全忘记字符串本⾝提供了⾮常丰富的⽅法。
所以这⾥提醒关注find replace startswith endswith这⼏个⽅法,这些基础的⽅法会⽐re库快很多,字⾯匹配⽤这些⽐较好,涉及到需要写正则表达式才能匹配下来的情况再re库
2.正则表达式中实现“或”的逻辑
⽐如下⾯拆分出单词,因为分隔符不同,所以要使⽤“或”的逻辑
import re
line = 'am are; friend, kind,good, foolish'python正则表达式不包含
当你通过“或”的逻辑写下这样的代码时
re.split(';s*|,s*| s*', line)
# ['am', 'are', 'friend', 'kind', 'good', 'foolish']
要想到可以改成这样
re.split('[,; ]s*', line)
# ['am', 'are', 'friend', 'kind', 'good', 'foolish']
另外,如果分隔符想保留下来,可以加⼀个括号
re.split('([,; ]s*)', line)
# ['am', ' ', 'are', '; ', 'friend', ', ', 'kind', ',', 'good', ', ', 'foolish']
更灵活的⽅式是⽤(?:),可以实现多字符的“或”逻辑。假设分隔符不是单个字符,则[]⽆法使⽤,如下所⽰,假如&&也想作为⼀个分隔符
import re
line = 'am are; friend, kind,good, foolish&& bc'
re.split('[,; ]s*', line)
# ['am', 'are', 'friend', 'kind', 'good', 'foolish&&', 'bc']
re.split('(?:;|,| |&&)s*', line)
# ['am', 'are', 'friend', 'kind', 'good', 'foolish', 'bc']
这种“或”逻辑在re.findall等其他功能中也经常使⽤。
3.字符串拼接
把a b两个字符串⽤空格拼接起来⼀般有三种⽅法
a = 'abc'
b = 'bcd'
' '.join((a, b))
a + ' ' + b
'{} {}'.format(a, b)
# 'abc bcd'
需要注意的是
(1)不要使⽤这种写法
s = ''
for p in parts:
s += p
使⽤加号来连接⼤量字符是⾮常低效率的,因为会产⽣⼤量中间变量,涉及内存复制和垃圾回收操作
可以将每次新的值append到列表中,最好是定义在函数⾥,每次yield出来,最后得到⼀个⽣成器,举例如下
def get_string(a):
yield 'This is a'
if a > 1:
yield 'big'
else:
yield 'small'
yield 'one.'
' '.join(get_string(2))
# 'This is a big one.'
' '.join(get_string(0))
# 'This is a small one.'
(2)避免不必要的拼接
print(a + ':' + b + ':' + c) # Ugly
print(':'.join([a, b, c])) # Still ugly
print(a, b, c, sep=':') # Better
4.⽂件读写时
我们是应该将字符串拼接得很⼤⼀起读进⽂件⾥呢,还是⼀⼩条⼀⼩条读进去呢?
如果每⼀条字符串都很短,那么拼起来读会好⼀些
如果字符串很长,拼起来会占很⼤内存,则分开读会好⼀些
5.配合⽣成器使⽤
def sample():
yield 'Is'
yield 'Chicago'
yield 'Not'
yield 'Chicago?'
上⾯的代码是值得推荐的。因为得到的⽣成器可定制性很⾼,想对它进⾏什么处理都可以,如
text = ''.join(sample())
或者
for part in sample():
f.write(part)
上⾯那么多yield看起来很别扭,但是想想我们经常把yield放在循环⾥,⼏百⼏千都⽤了,这⼏个不算什么的。
6. 字符串反斜杠和正则
我们来看看下⾯例⼦d和t的区别
'd' # 'd'
'd' # 'd'
r'd' # 'd'
r'd' #'d'
't' # 't'
r't' # 't'
't' # 't'
解读⼀下这个结果
t有特殊的转移含义,在字符串中应看做⼀个整体
⽽d应该看做两个字符,因为字符有转义功能,所以⽤表⽰反斜杠这个字符本⾝
如果想表⽰t这两个字符,可以前⾯加r或者直接⽤
'd'这种写法虽然也不会报错,但它不规范
在正则表达式中d表⽰数字,虽然有特殊含义,但它们依然是两个字符。下⾯例⼦三种⽅式都能得到相同的结果,但第⼀种写法不规范。
import re
line = 'a1b2c'
re.split('d', line) # bad
re.split('d', line) # good
re.split(r'd', line) # good
# ['a', 'b', 'c']
其实就是在写正则时加⼀个r的习惯。如果我们想写的pattern中既包含d⼜包含t,直接⽤r会将t理解为t,但其实这样也可以匹配到t,看下⾯这个例⼦
import re
line = 'a1b2ctd'
re.split(r'd|t', line) # ['a', 'b', 'c', 'd']
re.split('d|t', line) # ['a', 'b', 'c', 'd']
re.split('d|t', line) # ['a', 'b', 'c', 'd']
re.split('d|t', line) # ['a', 'b', 'c', 'd']
re.split('d|t', line) # ['a', 'b', 'c', 'd']
import re
line = r'a1b2ctd'
re.split('d|t', line) # ['a', 'b', 'ctd']
re.split('d|t', line) # ['a', 'b', 'ctd']
re.split('d|t', line) # ['a', 'b', 'c', 'd']
上⾯结果说明
匹配t,⽤t或t都可以
匹配t,必须⽤t,因为是在分别匹配三个字符
同理,我们也就很好地理解下⾯这两个例⼦
import re
line = 'a1b2cdd'
re.split('d', line) # ['a', 'b', 'cdd']
re.split('d|d', line) # ['a', 'b', 'c', 'd']
line = r'a1b2cdd'
re.split('d', line) # ['a', 'b', 'cdd']
re.split('d|d', line) # ['a', 'b', 'c', 'd']
因为'd'和r'd' 都相当于'd',和上⾯t的情形⼀样。
总结规律:正则表达式匹配的是字符本⾝,⽽不是print出来的样⼦。
⽐如匹配'd'或't',就看做三个字符,不管它其中⼀个是⽤于转义,print出来只有⼀个反斜杠。
⽐如匹配't',就看做两个字符⽤t,不管你print出来是否有特殊含义。⽽为什么t也可以呢?因为就像正则中⽤d匹配数字⼀样,正则中也⽤t来专门匹配t。
python正则表达式技巧
. * ?这三个符号⼀般都是作⽤在单个字符上,如果想作⽤到多个字符上,要这样⽤(?:abc)*
“或”⽤|例如匹配的pattern是ab|cd,则表⽰ab或cd,如果想表⽰b或c,就要这样做a(?:b|c)d
.*?是匹配除了n以外的字符,可以⽤flags=re.S令它可以匹配所有字符
1可以表⽰匹配中括号括起来的部分,如果有多个括号,可以⽤2或更⼤的数字。举例:通过替换,进⾏如下变换
原字符串:[array([1,2,3]), array([[1],[3],[4]])]
新字符串:[[1,2,3], [[1],[3],[4]]]
代码如下
import re
s = '[array([1,2,3]), array([[1],[3],[4]])]'
re.sub(r'array(([.*?]))', r'1', s)
{}()[]什么时候需要⽤:在pattern中,如果能构成正则的特殊⽤法,则如果想要表⽰它本⾝,就要加;在替换时,repl参数不需要加
s = '{} {1}'
re.sub('}', ':', s) # {: {1:'
re.sub('}', ':', s) # {: {1:'
re.sub('{}', ':', s) # ': {1}'
re.sub('{1}', ':', s) # error, pattern 部分不能出现 {1} 形式
re.sub('{1}', ':', s) # '{} :', 要加
re.sub('{1}', '{2}', s) # '{} {2}', repl 部分可以出现 {2} 形式
s = '() (1)'
re.sub(')', ':', s) # error, 对 () 来说,单独出现都要打
re.sub(')', ':', s) # '(: (1:'
re.sub('()', ':', s) # ':(:): :(:1:):', () 被当成空值处理了
re.sub('(1)', ':', s) # '() (:)', 正则表达式中没有 (1) 这种⽤法,所以没问题
re.sub(')', '(', s) # '(( (1(', repl 中没有问题
s = '[] [1]'
re.sub(']', ':', s) # '[: [1:', 右括号没问题
re.sub('[', ':', s) # error, 左括号不能单独出现
re.sub('[]', ':', s) # error
re.sub('[]', ':', s) # ': [1]', 只需要对左括号打即可
re.sub('[12]', ':', s) # '[] [:]', 这⾥表⽰的是正则的⽤法⽽不是它本⾝
re.sub('[12]', '[]', s) # '[] [[]]', repl 中没有问题
专栏信息
专栏主页:python编程
专栏⽬录:⽬录
版本说明:软件及包版本说明
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论