Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用正则表达式添加前导零_Python_Regex_Python 3.x - Fatal编程技术网

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