str.replace(old, new[, count])
Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.
该方法逻辑大致如下所示,存在多个 old
与 new
映射对时,需要串联使用多个 replace
方法, 效率较低。
matches = list(re.finditer(old, string))
if len(matches) == 0:
return
if count > 0:
for match in matches:
string[match.start(0): match.end(0)] = match.group(0)
count -= 1
if count == 0:
break
else:
for match in matches:
string[match.start(0): match.end(0)] = match.group(0)
在了解该方法之前,先了解类方法 str.maketrans
str.maketrans(x[, y[, z]])
- If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters (strings of length 1) to Unicode ordinals, strings (of arbitrary lengths) or None. Character keys will then be converted to ordinals.
- If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.
如果实参值是一个字典,则字典的键可以为“单个字符”、“Unicode 序数”, 字典值可以为“Unicode 序数”、“任意长度的字符串”、None。返回结果为一个字典,返回字典的键会转换为“Unicode 序数”, 返回字典的值与实参值一致。
如果传入两个实参值,则位置参数x
,y
必须是一个任意长度的字符串,会将同一位置的x
字符映射为y
字符,如果存在第三个实参值,位置参数z
中的每一个字符将与 None 建立映射关系:
assert len(x) == len(y)
d = dict()
for c_x, c_y in zip(x, y):
d.update({ord(c_x): c_y}
if z is not None:
for c_z in z:
d.update({ord(c_z}: None)
str.translate(table)
Return a copy of the string in which each character has been mapped through the given translation table.
位置参数table
接受的实参值类似于 str.maketrans
的返回结果,str.translate
会将字符串一一进行映射,如果字符对应的 Unicode 序数在实参值字典中,则可能会被映射为其它任意长度的字符串,或者被删除(Unicode 序数对应 None 时)。
re.sub(pattern, repl, string, count=0, flags=0)
Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl.
此函数的逻辑大致如下:
matches = list(re.finditer(pattern, string))
if len(matches) == 0: # If the pattern isn’t found, string is returned unchanged.
return string
else:
for match in matches:
if isinstance(repl, str): # repl can be a string or a function
string[match.start(0): match.end(0)] = repl
else:
string[match.start(0): match.end(0)] = repl(match)
return string
从左往右,将string
中匹配到pattern
并且非重叠的部分替换成repl
, repl
可以是一个字符串,也可以是一个函数。
“非重叠”的意思是指 pattern
在string
匹配的部分不存在重叠情况,如下:pattern
第一次匹配 string
中的 “12”, 第二次匹配 string
中的 “34”, 而非“23”,否则相邻的两个匹配存在重叠。
re.sub(r"(\d)(\d)", "99", "1234") # return "9999"
repl
为字符串类型时,支持“转义”与组内容的反向引用,即会对repl
中转义的部分进行特殊处理, 注意包含转义符号\
时,需使用 Python Raw String 表示法:
转义 ASCII 字符,并且是有效转义,替换后的结果采用转义后的字符,如 “\n” 表示一个换行符。
re.sub(r"(\d)(\d)", r"a\nb", "1234") # return 'a\nba\nb'
如果转义 ASCII 失败,则抛出异常:
re.sub(r"(\d)(\d)", r"\z", "1234") # 抛出异常 re.error: bad escape \z at position 0
如果与其它非 ASCII 转义,不做处理,仅保留非 ASCII 字符:
re.sub(r"(\d)(\d)", r"\&", "1234") # return '\\&\\&'
如果转义符号与组编号组合,则引用第编号组匹配到的内容:
re.sub(r"(\d)(\d)", r"\1", "1234") # return "13
# 如果第二项为 "\1", 则返回'\x01\x01'————双重转义,Python 与 正则表达式都将 “\” 作为转义字符。
# ord("\x01") -> 1
# chr(1) -> "\x01"
在 Python 3.9 中,除了支持组编号,也支持组别名,来引用特定组匹配到的内容,只是此种情形中,需在 pattern
中为组进行命名 :
re.sub(r"(?P\d)(?P\d)" , r"\" , "1234") # 使用组名 “13”
re.sub(r"(?P\d)(?P\d)" , r"\<1>", "1234") # 使用组编号 “13”
如果 repl
为函数, 则传入实参为 re.Match,函数返回值需为字符串, 如下:
def func(match):
if len(match.group(0)) > 1:
return "9" * len(match.group(0))
else:
return ""
re.sub(r"\d+", func, "a1b23c456") # return "ab99c999"