Python 用正则表达式添加前导零
假设我有一根像Python 用正则表达式添加前导零,python,regex,python-3.x,Python,Regex,Python 3.x,假设我有一根像 '1 - hello.mp3' '22 - hellox.mp3' '223 - hellox.mp3' 'hellox.mp3' 我希望输出的是 '001 - hello.mp3' '022 - hellox.mp3' '223 - hellox.mp3' 'hellox.mp3' 也就是说,如果起始值是数字,则添加0使其成为三位数字 在python中使用正则表达式有什么方法可以实现吗?是的,正则表达式可以做到这一点。与回调函数一起使用: import re def pa
'1 - hello.mp3'
'22 - hellox.mp3'
'223 - hellox.mp3'
'hellox.mp3'
我希望输出的是
'001 - hello.mp3'
'022 - hellox.mp3'
'223 - hellox.mp3'
'hellox.mp3'
也就是说,如果起始值是数字,则添加0使其成为三位数字
在python中使用正则表达式有什么方法可以实现吗?是的,正则表达式可以做到这一点。与回调函数一起使用:
import re
def pad_number(match):
number = int(match.group(1))
return format(number, "03d")
fixed_text = re.sub(r"^(\d+)", pad_number, text)
我使用的模式,^(\d+
匹配一个或多个数字(\d
是一个数字,+
将至少匹配一次,但将包含以下所有数字),但仅在字符串的开头(^
是此处的“文本开头”锚定)
然后,对于每个匹配的模式,调用pad\u number()
函数,该函数返回的字符串用于替换匹配的模式。由于模式使用捕获组(介于(
和)
之间的所有内容都是这样一个组),因此函数可以通过调用来访问匹配的数字
该函数将数字转换为整数,然后使用将该整数转换回文本,但这次是一个3个字符宽的0填充数字;这就是03
格式化指令告诉format()
生成的内容
请注意,模式可以匹配更多的数字,但是限制它们没有多大意义,除非有一个严格的上限(此时还需要对下一个不是数字的字符添加限制)。格式(数字,“03d”)
指令生成一个至少3位数宽的数字,但可以处理更长的值
演示:
再次,要考虑到这个方法不需要在开始处有4个或更多数字的特殊情况字符串;您只需获得更长的数字序列:
>>> re.sub(r"^(\d+)", pad_number, "4281 - 4 digits")
'4281 - 4 digits'
>>> re.sub(r"^(\d+)", pad_number, "428117 - 6 digits")
'428117 - 6 digits'
即使我们将\d
模式限制为最多只匹配3位数字(例如使用\d{1,3}
),也会发生这种情况
如果要使填充宽度可配置,可以将所有内容放入嵌套函数并使用字符串格式。你真的不需要
演示:
您特别要求使用正则表达式-(请参阅)-但也可以使用字符串操作:
data = [ '1 - hello.mp3', '22 - hellox.mp3', '223 - hellox.mp3', 'hellox.mp3' ]
def prefixZeroIfStartWithNumber(t):
"""Splits t at first space, if convertable to in, prefixes with three zeros
and returns it together with remainder of t. Else returns t."""
spl = t.split(" ",1)
try:
k = int(spl[0])
return f"{k:03} {spl[1]}" # format with zeros, add remainder
except (ValueError, IndexError):
return t
for text in data:
print(prefixZeroIfStartWithNumber(text))
输出:
001 - hello.mp3
022 - hellox.mp3
223 - hellox.mp3
hellox.mp3
另一种方式-据说更快:
def prefixZeroIfStartWithNumber(t):
number, _, remainder = t.partition(" ")
try:
k = int(number)
return f"{k:03} {remainder}" # format with zeros, add remainder
except (ValueError, IndexError):
return t
使用@martijn Pieters给出了正确的答案,但您也可以做同样简单的事情,运行此正则表达式两次:
regex = r"^(?=\d\d? )"
replacedby = "0"
^ asserts position at start of a line
Positive Lookahead (?=\d\d? )
\d matches a digit (equal to [0-9])
\d? matches a digit (equal to [0-9]) between zero and one times
Matches SPACE
I use the positive lookahead to match the lines starting with ## - but not including the ## - in the match, then I replace the start of the line with 0
为了简单起见,我在这里向您展示了相同的javascript:
const regex=/^(?=\d\d?)/gm;
常量str=`
1-hello.mp3
22-hellox.mp3
223-hellox.mp3
hellox.mp3`;
常量subst=`0`;
const result=str.replace(regex,subst).replace(regex,subst);
log('替换结果:',结果)代码>我很想听到我的答案中哪些没有帮助或错误,值得投反对票。这样我可以提高我的回答!有人dv两者-可能是“不尝试问题,让我们投票表决所有答案”dv…@MartijnPieters非常感谢!一个附带问题:是否可以将3作为函数参数或变量由用户输入?@william007:是的,通过字符串格式,您可以生成正则表达式模式,并且您希望使用闭包让替换函数拾取参数以在format()中使用
function.@william007:所以把所有东西都放在一个函数中(包括pad\u number()
函数,除了缩进以外不做任何更改),用width
作为参数,然后将format()
调用改为format(number,f“0{width}d”)
。疯狂的dv爱好者一定会喜欢它的。嗯,这至少让人相信,他们可能来自于一个认为我们没有回答这个问题的人,而不是因为我们在回答中遗漏了什么。专业提示:在固定字符串上只拆分一次时,请使用str.partition()
;对于那个用例来说速度更快。例如,首先,rest=t.partition(“”
)。
001 - hello.mp3
022 - hellox.mp3
223 - hellox.mp3
hellox.mp3
def prefixZeroIfStartWithNumber(t):
number, _, remainder = t.partition(" ")
try:
k = int(number)
return f"{k:03} {remainder}" # format with zeros, add remainder
except (ValueError, IndexError):
return t
regex = r"^(?=\d\d? )"
replacedby = "0"
^ asserts position at start of a line
Positive Lookahead (?=\d\d? )
\d matches a digit (equal to [0-9])
\d? matches a digit (equal to [0-9]) between zero and one times
Matches SPACE
I use the positive lookahead to match the lines starting with ## - but not including the ## - in the match, then I replace the start of the line with 0